X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=dali-toolkit%2Finternal%2Ffocus-manager%2Fkeyboard-focus-manager-impl.cpp;h=16f73862f322a06b52cb064de748d6be45a8b042;hb=e3929ce19d02903f5b5c9c356ae157183e37facb;hp=7117686cdaf5afb2c02546d9356c7a734bcb21bf;hpb=b3a97840ef9163145f3adc947cf1c6679911d754;p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git diff --git a/dali-toolkit/internal/focus-manager/keyboard-focus-manager-impl.cpp b/dali-toolkit/internal/focus-manager/keyboard-focus-manager-impl.cpp index 7117686..16f7386 100644 --- a/dali-toolkit/internal/focus-manager/keyboard-focus-manager-impl.cpp +++ b/dali-toolkit/internal/focus-manager/keyboard-focus-manager-impl.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019 Samsung Electronics Co., Ltd. + * Copyright (c) 2020 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,27 +21,28 @@ // EXTERNAL INCLUDES #include // for strcmp #include +#include #include -#include +#include #include #include -#include #include -#include +#include #include #include #include -#include -#include -#include #include +#include +#include // INTERNAL INCLUDES +#include #include #include #include -#include +#include #include +#include #include #include @@ -63,7 +64,7 @@ Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_KEY const char* const IS_FOCUS_GROUP_PROPERTY_NAME = "isKeyboardFocusGroup"; // This property will be replaced by a flag in Control. -const char* const FOCUS_BORDER_IMAGE_PATH = DALI_IMAGE_DIR "keyboard_focus.9.png"; +const char* const FOCUS_BORDER_IMAGE_FILE_NAME = "keyboard_focus.9.png"; BaseHandle Create() { @@ -122,15 +123,17 @@ KeyboardFocusManager::KeyboardFocusManager() mFocusedActorEnterKeySignal(), mCurrentFocusActor(), mFocusIndicatorActor(), - mIsFocusIndicatorShown( -1 ), + mFocusHistory(), + mSlotDelegate( this ), + mCustomAlgorithmInterface(NULL), + mCurrentFocusedWindow(), + mIsFocusIndicatorShown( UNKNOWN ), + mEnableFocusIndicator( ENABLE ), + mAlwaysShowIndicator( ALWAYS_SHOW ), mFocusGroupLoopEnabled( false ), mIsWaitingKeyboardFocusChangeCommit( false ), mClearFocusOnTouch( true ), - mEnableFocusIndicator( true ), - mAlwaysShowIndicator( true ), - mFocusHistory(), - mSlotDelegate( this ), - mCustomAlgorithmInterface(NULL) + mEnableDefaultAlgorithm(false) { // TODO: Get FocusIndicatorEnable constant from stylesheet to set mIsFocusIndicatorShown. @@ -146,7 +149,12 @@ void KeyboardFocusManager::OnAdaptorInit() for( auto iter = sceneHolders.begin(); iter != sceneHolders.end(); ++iter ) { ( *iter ).KeyEventSignal().Connect( mSlotDelegate, &KeyboardFocusManager::OnKeyEvent ); - ( *iter ).TouchSignal().Connect( mSlotDelegate, &KeyboardFocusManager::OnTouch ); + ( *iter ).TouchedSignal().Connect( mSlotDelegate, &KeyboardFocusManager::OnTouch ); + Dali::Window window = DevelWindow::DownCast( *iter ); + if( window ) + { + window.FocusChangeSignal().Connect( mSlotDelegate, &KeyboardFocusManager::OnWindowFocusChanged); + } } // Get notified when any new scene holder is created afterwards @@ -157,7 +165,12 @@ void KeyboardFocusManager::OnAdaptorInit() void KeyboardFocusManager::OnSceneHolderCreated( Dali::Integration::SceneHolder& sceneHolder ) { sceneHolder.KeyEventSignal().Connect( mSlotDelegate, &KeyboardFocusManager::OnKeyEvent ); - sceneHolder.TouchSignal().Connect( mSlotDelegate, &KeyboardFocusManager::OnTouch ); + sceneHolder.TouchedSignal().Connect( mSlotDelegate, &KeyboardFocusManager::OnTouch ); + Dali::Window window = DevelWindow::DownCast( sceneHolder ); + if( window ) + { + window.FocusChangeSignal().Connect( mSlotDelegate, &KeyboardFocusManager::OnWindowFocusChanged); + } } KeyboardFocusManager::~KeyboardFocusManager() @@ -170,9 +183,9 @@ void KeyboardFocusManager::GetConfigurationFromStyleManger() if( styleManager ) { Property::Map config = Toolkit::DevelStyleManager::GetConfigurations( styleManager ); - mAlwaysShowIndicator = config["alwaysShowFocus"].Get(); - mIsFocusIndicatorShown = static_cast(mAlwaysShowIndicator); - mClearFocusOnTouch = mIsFocusIndicatorShown ? false : true; + mAlwaysShowIndicator = config["alwaysShowFocus"].Get() ? ALWAYS_SHOW : NONE; + mIsFocusIndicatorShown = ( mAlwaysShowIndicator == ALWAYS_SHOW )? SHOW : HIDE; + mClearFocusOnTouch = ( mIsFocusIndicatorShown == SHOW ) ? false : true; } } @@ -180,7 +193,7 @@ bool KeyboardFocusManager::SetCurrentFocusActor( Actor actor ) { DALI_ASSERT_DEBUG( !mIsWaitingKeyboardFocusChangeCommit && "Calling this function in the PreFocusChangeSignal callback?" ); - if( mIsFocusIndicatorShown == -1 ) + if( mIsFocusIndicatorShown == UNKNOWN ) { GetConfigurationFromStyleManger(); } @@ -192,6 +205,32 @@ bool KeyboardFocusManager::DoSetCurrentFocusActor( Actor actor ) { bool success = false; + // If the parent's KEYBOARD_FOCUSABLE_CHILDREN is false, it cannot have focus. + if(actor) + { + Actor parent = actor.GetParent(); + while(parent) + { + if(!parent.GetProperty(DevelActor::Property::KEYBOARD_FOCUSABLE_CHILDREN)) + { + DALI_LOG_INFO(gLogFilter, Debug::General, "[%s:%d] Parent Actor has KEYBOARD_FOCUSABLE_CHILDREN false,\n", __FUNCTION__, __LINE__); + return false; + } + parent = parent.GetParent(); + } + } + + if(actor && actor.GetProperty(Actor::Property::KEYBOARD_FOCUSABLE) && actor.GetProperty(Actor::Property::CONNECTED_TO_SCENE)) + { + Integration::SceneHolder currentWindow = Integration::SceneHolder::Get( actor ); + + if( currentWindow.GetRootLayer() != mCurrentFocusedWindow.GetHandle()) + { + Layer rootLayer = currentWindow.GetRootLayer(); + mCurrentFocusedWindow = rootLayer; + } + } + Actor currentFocusedActor = GetCurrentFocusActor(); // If developer set focus on same actor, doing nothing @@ -205,9 +244,9 @@ bool KeyboardFocusManager::DoSetCurrentFocusActor( Actor actor ) } // Check whether the actor is in the stage and is keyboard focusable. - if( actor && actor.IsKeyboardFocusable() && actor.OnStage() ) + if( actor && actor.GetProperty< bool >( Actor::Property::KEYBOARD_FOCUSABLE ) && actor.GetProperty< bool >( Actor::Property::CONNECTED_TO_SCENE ) ) { - if( mIsFocusIndicatorShown && mEnableFocusIndicator ) + if( ( mIsFocusIndicatorShown == SHOW ) && ( mEnableFocusIndicator == ENABLE ) ) { actor.Add( GetFocusIndicatorActor() ); } @@ -231,6 +270,22 @@ bool KeyboardFocusManager::DoSetCurrentFocusActor( Actor actor ) // Save the current focused actor mCurrentFocusActor = actor; + bool focusedWindowFound = false; + for( unsigned int i = 0; i < mCurrentFocusActors.size(); i++ ) + { + if( mCurrentFocusActors[i].first == mCurrentFocusedWindow ) + { + mCurrentFocusActors[i].second = actor; + focusedWindowFound = true; + break; + } + } + if( !focusedWindowFound) + { + // A new window gains the focus, so store the focused actor in that window. + mCurrentFocusActors.push_back( std::pair< WeakHandle< Layer>, WeakHandle< Actor > >( mCurrentFocusedWindow , actor )); + } + Toolkit::Control newlyFocusedControl = Toolkit::Control::DownCast(actor); if( newlyFocusedControl ) { @@ -262,16 +317,39 @@ bool KeyboardFocusManager::DoSetCurrentFocusActor( Actor actor ) Actor KeyboardFocusManager::GetCurrentFocusActor() { Actor actor = mCurrentFocusActor.GetHandle(); - if( actor && ! actor.OnStage() ) + + if( actor && ! actor.GetProperty< bool >( Actor::Property::CONNECTED_TO_SCENE ) ) { // If the actor has been removed from the stage, then it should not be focused - actor.Reset(); mCurrentFocusActor.Reset(); } return actor; } +Actor KeyboardFocusManager::GetFocusActorFromCurrentWindow() +{ + Actor actor; + unsigned int index; + for( index = 0; index < mCurrentFocusActors.size(); index++ ) + { + if( mCurrentFocusActors[index].first == mCurrentFocusedWindow ) + { + actor = mCurrentFocusActors[index].second.GetHandle(); + break; + } + } + + if( actor && ! actor.GetProperty< bool >( Actor::Property::CONNECTED_TO_SCENE ) ) + { + // If the actor has been removed from the window, then the window doesn't have any focused actor + actor.Reset(); + mCurrentFocusActors.erase( mCurrentFocusActors.begin() + index ); + } + + return actor; +} + Actor KeyboardFocusManager::GetCurrentFocusGroup() { return GetFocusGroup(GetCurrentFocusActor()); @@ -292,7 +370,7 @@ void KeyboardFocusManager::MoveFocusBackward() Actor target = mFocusHistory[ mFocusHistory.size() -1 ].GetHandle(); // Impl of Actor is not null - if( target && target.OnStage() ) + if( target && target.GetProperty< bool >( Actor::Property::CONNECTED_TO_SCENE ) ) { // Delete pre focused actor in history because it will pushed again by SetCurrentFocusActor() mFocusHistory.pop_back(); @@ -328,7 +406,12 @@ Toolkit::Control KeyboardFocusManager::GetParentLayoutControl(Actor actor) const Actor parent; if(actor) { - rootActor = Integration::SceneHolder::Get( actor ).GetRootLayer(); + Integration::SceneHolder window = Integration::SceneHolder::Get( actor ); + if ( window ) + { + rootActor = window.GetRootLayer(); + } + parent = actor.GetParent(); } @@ -410,7 +493,11 @@ bool KeyboardFocusManager::MoveFocus(Toolkit::Control::KeyboardFocus::Direction if( !nextFocusableActor ) { - nextFocusableActor = Integration::SceneHolder::Get( currentFocusActor ).GetRootLayer().FindChildById( actorId ); + Integration::SceneHolder window = Integration::SceneHolder::Get( currentFocusActor ); + if ( window ) + { + nextFocusableActor = window.GetRootLayer().FindChildById( actorId ); + } } } } @@ -432,9 +519,18 @@ bool KeyboardFocusManager::MoveFocus(Toolkit::Control::KeyboardFocus::Direction nextFocusableActor = mPreFocusChangeSignal.Emit( currentFocusActor, Actor(), direction ); mIsWaitingKeyboardFocusChangeCommit = false; } + else if(mEnableDefaultAlgorithm) + { + // We should find it among the actors nearby. + Integration::SceneHolder window = Integration::SceneHolder::Get(currentFocusActor); + if(window) + { + nextFocusableActor = Toolkit::FocusFinder::GetNearestFocusableActor(window.GetRootLayer(), currentFocusActor, direction); + } + } } - if( nextFocusableActor && nextFocusableActor.IsKeyboardFocusable() ) + if( nextFocusableActor && nextFocusableActor.GetProperty< bool >( Actor::Property::KEYBOARD_FOCUSABLE ) ) { // Whether the next focusable actor is a layout control if( IsLayoutControl( nextFocusableActor ) ) @@ -460,7 +556,7 @@ bool KeyboardFocusManager::DoMoveFocusWithinLayoutControl(Toolkit::Control contr Actor nextFocusableActor = GetImplementation( control ).GetNextKeyboardFocusableActor(actor, direction, mFocusGroupLoopEnabled); if(nextFocusableActor) { - if(!nextFocusableActor.IsKeyboardFocusable()) + if(!nextFocusableActor.GetProperty< bool >( Actor::Property::KEYBOARD_FOCUSABLE )) { // If the actor is not focusable, ask the same layout control for the next actor to focus return DoMoveFocusWithinLayoutControl(control, nextFocusableActor, direction); @@ -479,7 +575,7 @@ bool KeyboardFocusManager::DoMoveFocusWithinLayoutControl(Toolkit::Control contr mIsWaitingKeyboardFocusChangeCommit = false; } - if (committedFocusActor && committedFocusActor.IsKeyboardFocusable()) + if (committedFocusActor && committedFocusActor.GetProperty< bool >( Actor::Property::KEYBOARD_FOCUSABLE )) { // Whether the commited focusable actor is a layout control if(IsLayoutControl(committedFocusActor)) @@ -584,7 +680,7 @@ void KeyboardFocusManager::ClearFocus() } mCurrentFocusActor.Reset(); - mIsFocusIndicatorShown = static_cast(mAlwaysShowIndicator); + mIsFocusIndicatorShown = ( mAlwaysShowIndicator == ALWAYS_SHOW ) ? SHOW : HIDE; } void KeyboardFocusManager::SetFocusGroupLoop(bool enabled) @@ -662,15 +758,16 @@ Actor KeyboardFocusManager::GetFocusIndicatorActor() if( ! mFocusIndicatorActor ) { // Create the default if it hasn't been set and one that's shared by all the keyboard focusable actors - mFocusIndicatorActor = Toolkit::ImageView::New( FOCUS_BORDER_IMAGE_PATH ); + const std::string imageDirPath = AssetManager::GetDaliImagePath(); + mFocusIndicatorActor = Toolkit::ImageView::New( imageDirPath + FOCUS_BORDER_IMAGE_FILE_NAME ); // Apply size constraint to the focus indicator mFocusIndicatorActor.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS ); } - mFocusIndicatorActor.SetParentOrigin( ParentOrigin::CENTER ); - mFocusIndicatorActor.SetAnchorPoint( AnchorPoint::CENTER ); - mFocusIndicatorActor.SetPosition(0.0f, 0.0f); + mFocusIndicatorActor.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER ); + mFocusIndicatorActor.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER ); + mFocusIndicatorActor.SetProperty( Actor::Property::POSITION, Vector2(0.0f, 0.0f)); return mFocusIndicatorActor; } @@ -682,25 +779,25 @@ void KeyboardFocusManager::OnKeyEvent(const KeyEvent& event) Toolkit::AccessibilityManager accessibilityManager = Toolkit::AccessibilityManager::Get(); - std::string keyName = event.keyPressedName; + std::string keyName = event.GetKeyName(); - if( mIsFocusIndicatorShown == -1 ) + if( mIsFocusIndicatorShown == UNKNOWN ) { GetConfigurationFromStyleManger(); } bool isFocusStartableKey = false; - if(event.state == KeyEvent::Down) + if(event.GetState() == KeyEvent::DOWN) { if (keyName == "Left") { if(!isAccessibilityEnabled) { - if(!mIsFocusIndicatorShown) + if(mIsFocusIndicatorShown == HIDE) { // Show focus indicator - mIsFocusIndicatorShown = 1; + mIsFocusIndicatorShown = SHOW; } else { @@ -720,10 +817,10 @@ void KeyboardFocusManager::OnKeyEvent(const KeyEvent& event) { if(!isAccessibilityEnabled) { - if(!mIsFocusIndicatorShown) + if( mIsFocusIndicatorShown == HIDE ) { // Show focus indicator - mIsFocusIndicatorShown = 1; + mIsFocusIndicatorShown = SHOW; } else { @@ -741,10 +838,10 @@ void KeyboardFocusManager::OnKeyEvent(const KeyEvent& event) } else if (keyName == "Up" && !isAccessibilityEnabled) { - if(!mIsFocusIndicatorShown) + if( mIsFocusIndicatorShown == HIDE ) { // Show focus indicator - mIsFocusIndicatorShown = 1; + mIsFocusIndicatorShown = SHOW; } else { @@ -756,10 +853,10 @@ void KeyboardFocusManager::OnKeyEvent(const KeyEvent& event) } else if (keyName == "Down" && !isAccessibilityEnabled) { - if(!mIsFocusIndicatorShown) + if( mIsFocusIndicatorShown == HIDE ) { // Show focus indicator - mIsFocusIndicatorShown = 1; + mIsFocusIndicatorShown = SHOW; } else { @@ -771,10 +868,10 @@ void KeyboardFocusManager::OnKeyEvent(const KeyEvent& event) } else if (keyName == "Prior" && !isAccessibilityEnabled) { - if(!mIsFocusIndicatorShown) + if( mIsFocusIndicatorShown == HIDE ) { // Show focus indicator - mIsFocusIndicatorShown = 1; + mIsFocusIndicatorShown = SHOW; } else { @@ -786,10 +883,10 @@ void KeyboardFocusManager::OnKeyEvent(const KeyEvent& event) } else if (keyName == "Next" && !isAccessibilityEnabled) { - if(!mIsFocusIndicatorShown) + if( mIsFocusIndicatorShown == HIDE ) { // Show focus indicator - mIsFocusIndicatorShown = 1; + mIsFocusIndicatorShown = SHOW; } else { @@ -801,26 +898,34 @@ void KeyboardFocusManager::OnKeyEvent(const KeyEvent& event) } else if (keyName == "Tab" && !isAccessibilityEnabled) { - if(!mIsFocusIndicatorShown) + if( mIsFocusIndicatorShown == HIDE ) { // Show focus indicator - mIsFocusIndicatorShown = 1; + mIsFocusIndicatorShown = SHOW; } else { // "Tab" key changes the focus group in the forward direction and // "Shift-Tab" key changes it in the backward direction. - DoMoveFocusToNextFocusGroup(!event.IsShiftModifier()); + if(!DoMoveFocusToNextFocusGroup(!event.IsShiftModifier())) + { + // If the focus group is not changed, Move the focus towards right, "Shift-Tap" key moves the focus towards left. + if(!MoveFocus(event.IsShiftModifier() ? Toolkit::Control::KeyboardFocus::LEFT : Toolkit::Control::KeyboardFocus::RIGHT)) + { + // If the focus is not moved, Move the focus towards down, "Shift-Tap" key moves the focus towards up. + MoveFocus(event.IsShiftModifier() ? Toolkit::Control::KeyboardFocus::UP : Toolkit::Control::KeyboardFocus::DOWN); + } + } } isFocusStartableKey = true; } else if (keyName == "space" && !isAccessibilityEnabled) { - if(!mIsFocusIndicatorShown) + if( mIsFocusIndicatorShown == HIDE ) { // Show focus indicator - mIsFocusIndicatorShown = 1; + mIsFocusIndicatorShown = SHOW; } isFocusStartableKey = true; @@ -828,10 +933,10 @@ void KeyboardFocusManager::OnKeyEvent(const KeyEvent& event) else if (keyName == "" && !isAccessibilityEnabled) { // Check the fake key event for evas-plugin case - if(!mIsFocusIndicatorShown) + if( mIsFocusIndicatorShown == HIDE ) { // Show focus indicator - mIsFocusIndicatorShown = 1; + mIsFocusIndicatorShown = SHOW; } isFocusStartableKey = true; @@ -844,14 +949,14 @@ void KeyboardFocusManager::OnKeyEvent(const KeyEvent& event) { } } - else if(event.state == KeyEvent::Up) + else if(event.GetState() == KeyEvent::UP) { if (keyName == "Return") { - if(!mIsFocusIndicatorShown && !isAccessibilityEnabled) + if((mIsFocusIndicatorShown == HIDE) && !isAccessibilityEnabled) { // Show focus indicator - mIsFocusIndicatorShown = 1; + mIsFocusIndicatorShown = SHOW; } else { @@ -876,12 +981,12 @@ void KeyboardFocusManager::OnKeyEvent(const KeyEvent& event) } } - if(isFocusStartableKey && mIsFocusIndicatorShown && !isAccessibilityEnabled) + if(isFocusStartableKey && ( mIsFocusIndicatorShown == SHOW ) && !isAccessibilityEnabled) { Actor actor = GetCurrentFocusActor(); if( actor ) { - if( mEnableFocusIndicator ) + if( mEnableFocusIndicator == ENABLE ) { // Make sure the focused actor is highlighted actor.Add( GetFocusIndicatorActor() ); @@ -896,21 +1001,52 @@ void KeyboardFocusManager::OnKeyEvent(const KeyEvent& event) } } -void KeyboardFocusManager::OnTouch(const TouchData& touch) +void KeyboardFocusManager::OnTouch(const TouchEvent& touch) { - // if mIsFocusIndicatorShown is -1, it means Configuration is not loaded. + // if mIsFocusIndicatorShown is UNKNOWN, it means Configuration is not loaded. // Try to load configuration. - if( mIsFocusIndicatorShown == -1 ) + if( mIsFocusIndicatorShown == UNKNOWN ) { GetConfigurationFromStyleManger(); } // Clear the focus when user touch the screen. // We only do this on a Down event, otherwise the clear action may override a manually focused actor. - // If mClearFocusOnTouch is false, do not clear the focus even if user touch the screen. - if( (( touch.GetPointCount() < 1 ) || ( touch.GetState( 0 ) == PointState::DOWN )) && mClearFocusOnTouch ) + if(((touch.GetPointCount() < 1) || (touch.GetState(0) == PointState::DOWN))) { - ClearFocus(); + // If mClearFocusOnTouch is false, do not clear the focus even if user touch the screen. + if(mClearFocusOnTouch) + { + ClearFocus(); + } + + // If KEYBOARD_FOCUSABLE and TOUCH_FOCUSABLE is true, set focus actor + Actor hitActor = touch.GetHitActor(0); + if(hitActor && hitActor.GetProperty(Actor::Property::KEYBOARD_FOCUSABLE) && hitActor.GetProperty(DevelActor::Property::TOUCH_FOCUSABLE)) + { + SetCurrentFocusActor(hitActor); + } + } +} + +void KeyboardFocusManager::OnWindowFocusChanged(Window window, bool focusIn ) +{ + if( focusIn && mCurrentFocusedWindow.GetHandle() != window.GetRootLayer() ) + { + // Change Current Focused Window + Layer rootLayer = window.GetRootLayer(); + mCurrentFocusedWindow = rootLayer; + + // Get Current Focused Actor from window + Actor currentFocusedActor = GetFocusActorFromCurrentWindow(); + SetCurrentFocusActor( currentFocusedActor ); + + if( currentFocusedActor && ( mEnableFocusIndicator == ENABLE ) ) + { + // Make sure the focused actor is highlighted + currentFocusedActor.Add( GetFocusIndicatorActor() ); + mIsFocusIndicatorShown = SHOW; + } } } @@ -978,12 +1114,23 @@ void KeyboardFocusManager::EnableFocusIndicator(bool enable) mFocusIndicatorActor.Unparent(); } - mEnableFocusIndicator = enable; + mEnableFocusIndicator = enable? ENABLE : DISABLE; + } bool KeyboardFocusManager::IsFocusIndicatorEnabled() const { - return mEnableFocusIndicator; + return ( mEnableFocusIndicator == ENABLE ); +} + +void KeyboardFocusManager::EnableDefaultAlgorithm(bool enable) +{ + mEnableDefaultAlgorithm = enable; +} + +bool KeyboardFocusManager::IsDefaultAlgorithmEnabled() const +{ + return mEnableDefaultAlgorithm; } } // namespace Internal