X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git;a=blobdiff_plain;f=dali-toolkit%2Finternal%2Ffocus-manager%2Fkeyboard-focus-manager-impl.cpp;h=b10ff63543615eba148a50229a015e209817bce1;hp=3f398c58c3e4ee3f340b312338dd6c1280fe5413;hb=982261bb2c86fbe87afc89deb1e24d272de02ae6;hpb=886ad3dc35609a01504e03707996a4c102ef23e7 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 3f398c5..b10ff63 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) 2017 Samsung Electronics Co., Ltd. + * Copyright (c) 2021 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. @@ -19,60 +19,59 @@ #include "keyboard-focus-manager-impl.h" // 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 +#include +#include // for strcmp // INTERNAL INCLUDES -#include +#include +#include +#include +#include #include +#include #include -#include -#include #include -#include +#include namespace Dali { - namespace Toolkit { - namespace Internal { - namespace // Unnamed namespace { - #if defined(DEBUG_ENABLED) Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_KEYBOARD_FOCUS_MANAGER"); #endif 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() { BaseHandle handle = KeyboardFocusManager::Get(); - if ( !handle ) + if(!handle) { - SingletonService singletonService( SingletonService::Get() ); - if ( singletonService ) + SingletonService singletonService(SingletonService::Get()); + if(singletonService) { - Toolkit::KeyboardFocusManager manager = Toolkit::KeyboardFocusManager( new Internal::KeyboardFocusManager() ); - singletonService.Register( typeid( manager ), manager ); + Toolkit::KeyboardFocusManager manager = Toolkit::KeyboardFocusManager(new Internal::KeyboardFocusManager()); + singletonService.Register(typeid(manager), manager); handle = manager; } } @@ -80,12 +79,12 @@ BaseHandle Create() return handle; } -DALI_TYPE_REGISTRATION_BEGIN_CREATE( Toolkit::KeyboardFocusManager, Dali::BaseHandle, Create, true ) +DALI_TYPE_REGISTRATION_BEGIN_CREATE(Toolkit::KeyboardFocusManager, Dali::BaseHandle, Create, true) -DALI_SIGNAL_REGISTRATION( Toolkit, KeyboardFocusManager, "keyboardPreFocusChange", SIGNAL_PRE_FOCUS_CHANGE ) -DALI_SIGNAL_REGISTRATION( Toolkit, KeyboardFocusManager, "keyboardFocusChanged", SIGNAL_FOCUS_CHANGED ) -DALI_SIGNAL_REGISTRATION( Toolkit, KeyboardFocusManager, "keyboardFocusGroupChanged", SIGNAL_FOCUS_GROUP_CHANGED ) -DALI_SIGNAL_REGISTRATION( Toolkit, KeyboardFocusManager, "keyboardFocusedActorEnterKey", SIGNAL_FOCUSED_ACTOR_ENTER_KEY ) +DALI_SIGNAL_REGISTRATION(Toolkit, KeyboardFocusManager, "keyboardPreFocusChange", SIGNAL_PRE_FOCUS_CHANGE) +DALI_SIGNAL_REGISTRATION(Toolkit, KeyboardFocusManager, "keyboardFocusChanged", SIGNAL_FOCUS_CHANGED) +DALI_SIGNAL_REGISTRATION(Toolkit, KeyboardFocusManager, "keyboardFocusGroupChanged", SIGNAL_FOCUS_GROUP_CHANGED) +DALI_SIGNAL_REGISTRATION(Toolkit, KeyboardFocusManager, "keyboardFocusedActorEnterKey", SIGNAL_FOCUSED_ACTOR_ENTER_KEY) DALI_TYPE_REGISTRATION_END() @@ -97,15 +96,15 @@ Toolkit::KeyboardFocusManager KeyboardFocusManager::Get() { Toolkit::KeyboardFocusManager manager; - SingletonService singletonService( SingletonService::Get() ); - if ( singletonService ) + SingletonService singletonService(SingletonService::Get()); + if(singletonService) { // Check whether the keyboard focus manager is already created - Dali::BaseHandle handle = singletonService.GetSingleton( typeid( Toolkit::KeyboardFocusManager ) ); + Dali::BaseHandle handle = singletonService.GetSingleton(typeid(Toolkit::KeyboardFocusManager)); if(handle) { // If so, downcast the handle of singleton to keyboard focus manager - manager = Toolkit::KeyboardFocusManager( dynamic_cast< KeyboardFocusManager* >( handle.GetObjectPtr() ) ); + manager = Toolkit::KeyboardFocusManager(dynamic_cast(handle.GetObjectPtr())); } } @@ -119,17 +118,54 @@ KeyboardFocusManager::KeyboardFocusManager() mFocusedActorEnterKeySignal(), mCurrentFocusActor(), mFocusIndicatorActor(), - mIsFocusIndicatorEnabled( -1 ), - mFocusGroupLoopEnabled( false ), - mIsWaitingKeyboardFocusChangeCommit( false ), - mClearFocusOnTouch( true ), mFocusHistory(), - mSlotDelegate( this ), - mCustomAlgorithmInterface(NULL) + mSlotDelegate(this), + mCustomAlgorithmInterface(NULL), + mCurrentFocusedWindow(), + mIsFocusIndicatorShown(UNKNOWN), + mEnableFocusIndicator(ENABLE), + mAlwaysShowIndicator(ALWAYS_SHOW), + mFocusGroupLoopEnabled(false), + mIsWaitingKeyboardFocusChangeCommit(false), + mClearFocusOnTouch(true), + mEnableDefaultAlgorithm(false) +{ + // TODO: Get FocusIndicatorEnable constant from stylesheet to set mIsFocusIndicatorShown. + + LifecycleController::Get().InitSignal().Connect(mSlotDelegate, &KeyboardFocusManager::OnAdaptorInit); +} + +void KeyboardFocusManager::OnAdaptorInit() +{ + if(Adaptor::IsAvailable()) + { + // Retrieve all the existing scene holders + Dali::SceneHolderList sceneHolders = Adaptor::Get().GetSceneHolders(); + for(auto iter = sceneHolders.begin(); iter != sceneHolders.end(); ++iter) + { + (*iter).KeyEventSignal().Connect(mSlotDelegate, &KeyboardFocusManager::OnKeyEvent); + (*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 + Adaptor::Get().WindowCreatedSignal().Connect(mSlotDelegate, &KeyboardFocusManager::OnSceneHolderCreated); + } +} + +void KeyboardFocusManager::OnSceneHolderCreated(Dali::Integration::SceneHolder& sceneHolder) { - // TODO: Get FocusIndicatorEnable constant from stylesheet to set mIsFocusIndicatorEnabled. - Stage::GetCurrent().KeyEventSignal().Connect( mSlotDelegate, &KeyboardFocusManager::OnKeyEvent); - Stage::GetCurrent().TouchSignal().Connect( mSlotDelegate, &KeyboardFocusManager::OnTouch ); + sceneHolder.KeyEventSignal().Connect(mSlotDelegate, &KeyboardFocusManager::OnKeyEvent); + sceneHolder.TouchedSignal().Connect(mSlotDelegate, &KeyboardFocusManager::OnTouch); + Dali::Window window = DevelWindow::DownCast(sceneHolder); + if(window) + { + window.FocusChangeSignal().Connect(mSlotDelegate, &KeyboardFocusManager::OnWindowFocusChanged); + } } KeyboardFocusManager::~KeyboardFocusManager() @@ -138,37 +174,48 @@ KeyboardFocusManager::~KeyboardFocusManager() void KeyboardFocusManager::GetConfigurationFromStyleManger() { - Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get(); - if( styleManager ) - { - Property::Map config = Toolkit::DevelStyleManager::GetConfigurations( styleManager ); - mIsFocusIndicatorEnabled = static_cast(config["alwaysShowFocus"].Get()); - mClearFocusOnTouch = mIsFocusIndicatorEnabled ? false : true; - } + Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get(); + if(styleManager) + { + Property::Map config = Toolkit::DevelStyleManager::GetConfigurations(styleManager); + mAlwaysShowIndicator = config["alwaysShowFocus"].Get() ? ALWAYS_SHOW : NONE; + mIsFocusIndicatorShown = (mAlwaysShowIndicator == ALWAYS_SHOW) ? SHOW : HIDE; + mClearFocusOnTouch = (mIsFocusIndicatorShown == SHOW) ? false : true; + } } -bool KeyboardFocusManager::SetCurrentFocusActor( Actor actor ) +bool KeyboardFocusManager::SetCurrentFocusActor(Actor actor) { - DALI_ASSERT_DEBUG( !mIsWaitingKeyboardFocusChangeCommit && "Calling this function in the PreFocusChangeSignal callback?" ); + DALI_ASSERT_DEBUG(!mIsWaitingKeyboardFocusChangeCommit && "Calling this function in the PreFocusChangeSignal callback?"); - if( mIsFocusIndicatorEnabled == -1 ) + if(mIsFocusIndicatorShown == UNKNOWN) { GetConfigurationFromStyleManger(); } - return DoSetCurrentFocusActor( actor ); + return DoSetCurrentFocusActor(actor); } -bool KeyboardFocusManager::DoSetCurrentFocusActor( Actor actor ) +bool KeyboardFocusManager::DoSetCurrentFocusActor(Actor actor) { bool success = false; + 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 - if( actor == currentFocusedActor ) + if(actor == currentFocusedActor) { - if( !actor ) + if(!actor) { return false; } @@ -176,50 +223,66 @@ 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(Actor::Property::KEYBOARD_FOCUSABLE) && actor.GetProperty(Actor::Property::CONNECTED_TO_SCENE)) { - if( mIsFocusIndicatorEnabled ) + if((mIsFocusIndicatorShown == SHOW) && (mEnableFocusIndicator == ENABLE)) { - actor.Add( GetFocusIndicatorActor() ); + actor.Add(GetFocusIndicatorActor()); } // Send notification for the change of focus actor - if( !mFocusChangedSignal.Empty() ) + if(!mFocusChangedSignal.Empty()) { mFocusChangedSignal.Emit(currentFocusedActor, actor); } Toolkit::Control currentlyFocusedControl = Toolkit::Control::DownCast(currentFocusedActor); - if( currentlyFocusedControl ) + if(currentlyFocusedControl) { // Do we need it to remember if it was previously DISABLED? - currentlyFocusedControl.SetProperty(DevelControl::Property::STATE, DevelControl::NORMAL ); + currentlyFocusedControl.SetProperty(DevelControl::Property::STATE, DevelControl::NORMAL); currentlyFocusedControl.ClearKeyInputFocus(); } - DALI_LOG_INFO( gLogFilter, Debug::General, "[%s:%d] Focus Changed\n", __FUNCTION__, __LINE__); + DALI_LOG_INFO(gLogFilter, Debug::General, "[%s:%d] Focus Changed\n", __FUNCTION__, __LINE__); // 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 >(mCurrentFocusedWindow, actor)); + } + Toolkit::Control newlyFocusedControl = Toolkit::Control::DownCast(actor); - if( newlyFocusedControl ) + if(newlyFocusedControl) { - newlyFocusedControl.SetProperty(DevelControl::Property::STATE, DevelControl::FOCUSED ); + newlyFocusedControl.SetProperty(DevelControl::Property::STATE, DevelControl::FOCUSED); newlyFocusedControl.SetKeyInputFocus(); } // Push Current Focused Actor to FocusHistory - mFocusHistory.push_back( actor ); + mFocusHistory.push_back(actor); // Delete first element before add new element when Stack is full. - if( mFocusHistory.size() > MAX_HISTORY_AMOUNT ) + if(mFocusHistory.size() > MAX_HISTORY_AMOUNT) { - FocusStackIterator beginPos = mFocusHistory.begin(); - mFocusHistory.erase( beginPos ); + FocusStackIterator beginPos = mFocusHistory.begin(); + mFocusHistory.erase(beginPos); } - DALI_LOG_INFO( gLogFilter, Debug::General, "[%s:%d] SUCCEED\n", __FUNCTION__, __LINE__); + DALI_LOG_INFO(gLogFilter, Debug::General, "[%s:%d] SUCCEED\n", __FUNCTION__, __LINE__); success = true; } else @@ -233,16 +296,39 @@ bool KeyboardFocusManager::DoSetCurrentFocusActor( Actor actor ) Actor KeyboardFocusManager::GetCurrentFocusActor() { Actor actor = mCurrentFocusActor.GetHandle(); - if( actor && ! actor.OnStage() ) + + if(actor && !actor.GetProperty(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(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()); @@ -251,23 +337,23 @@ Actor KeyboardFocusManager::GetCurrentFocusGroup() void KeyboardFocusManager::MoveFocusBackward() { // Find Pre Focused Actor when the list size is more than 1 - if( mFocusHistory.size() > 1 ) + if(mFocusHistory.size() > 1) { // Delete current focused actor in history mFocusHistory.pop_back(); // If pre-focused actors are not on stage or deleted, remove them in stack - while( mFocusHistory.size() > 0 ) + while(mFocusHistory.size() > 0) { // Get pre focused actor - Actor target = mFocusHistory[ mFocusHistory.size() -1 ].GetHandle(); + Actor target = mFocusHistory[mFocusHistory.size() - 1].GetHandle(); // Impl of Actor is not null - if( target && target.OnStage() ) + if(target && target.GetProperty(Actor::Property::CONNECTED_TO_SCENE)) { // Delete pre focused actor in history because it will pushed again by SetCurrentFocusActor() mFocusHistory.pop_back(); - SetCurrentFocusActor( target ); + SetCurrentFocusActor(target); break; } else @@ -278,10 +364,10 @@ void KeyboardFocusManager::MoveFocusBackward() } // if there is no actor which can get focus, then push current focus actor in stack again - if( mFocusHistory.size() == 0 ) + if(mFocusHistory.size() == 0) { Actor currentFocusedActor = GetCurrentFocusActor(); - mFocusHistory.push_back( currentFocusedActor ); + mFocusHistory.push_back(currentFocusedActor); } } } @@ -289,20 +375,26 @@ void KeyboardFocusManager::MoveFocusBackward() bool KeyboardFocusManager::IsLayoutControl(Actor actor) const { Toolkit::Control control = Toolkit::Control::DownCast(actor); - return control && GetImplementation( control ).IsKeyboardNavigationSupported(); + return control && GetImplementation(control).IsKeyboardNavigationSupported(); } Toolkit::Control KeyboardFocusManager::GetParentLayoutControl(Actor actor) const { // Get the actor's parent layout control that supports two dimensional keyboard navigation - Actor rootActor = Stage::GetCurrent().GetRootLayer(); + Actor rootActor; Actor parent; if(actor) { + Integration::SceneHolder window = Integration::SceneHolder::Get(actor); + if(window) + { + rootActor = window.GetRootLayer(); + } + parent = actor.GetParent(); } - while( parent && !IsLayoutControl(parent) && parent != rootActor ) + while(parent && !IsLayoutControl(parent) && parent != rootActor) { parent = parent.GetParent(); } @@ -317,28 +409,28 @@ bool KeyboardFocusManager::MoveFocus(Toolkit::Control::KeyboardFocus::Direction bool succeed = false; // Go through the actor's hierarchy until we find a layout control that knows how to move the focus - Toolkit::Control parentLayoutControl = GetParentLayoutControl( currentFocusActor ); - while( parentLayoutControl && !succeed ) + Toolkit::Control parentLayoutControl = GetParentLayoutControl(currentFocusActor); + while(parentLayoutControl && !succeed) { - succeed = DoMoveFocusWithinLayoutControl( parentLayoutControl, currentFocusActor, direction ); - parentLayoutControl = GetParentLayoutControl( parentLayoutControl ); + succeed = DoMoveFocusWithinLayoutControl(parentLayoutControl, currentFocusActor, direction); + parentLayoutControl = GetParentLayoutControl(parentLayoutControl); } - if( !succeed ) + if(!succeed) { Actor nextFocusableActor; Toolkit::Control currentFocusControl = Toolkit::Control::DownCast(currentFocusActor); // If the current focused actor is a control, then find the next focusable actor via the focusable properties. - if( currentFocusControl ) + if(currentFocusControl) { - int actorId = -1; - Property::Index index = Property::INVALID_INDEX; + int actorId = -1; + Property::Index index = Property::INVALID_INDEX; Property::Value value; // Find property index based upon focus direction - switch ( direction ) + switch(direction) { case Toolkit::Control::KeyboardFocus::LEFT: { @@ -365,58 +457,67 @@ bool KeyboardFocusManager::MoveFocus(Toolkit::Control::KeyboardFocus::Direction } // If the focusable property is set then determine next focusable actor - if( index != Property::INVALID_INDEX) + if(index != Property::INVALID_INDEX) { - value = currentFocusActor.GetProperty( index ); + value = currentFocusActor.GetProperty(index); actorId = value.Get(); // If actor's id is valid then find actor form actor's id. The actor should be on the stage. - if( actorId != -1 ) + if(actorId != -1) { - if( currentFocusActor.GetParent() ) + if(currentFocusActor.GetParent()) { - nextFocusableActor = currentFocusActor.GetParent().FindChildById( actorId ); + nextFocusableActor = currentFocusActor.GetParent().FindChildById(actorId); } - if( !nextFocusableActor ) + if(!nextFocusableActor) { - nextFocusableActor = Stage::GetCurrent().GetRootLayer().FindChildById( actorId ); + Integration::SceneHolder window = Integration::SceneHolder::Get(currentFocusActor); + if(window) + { + nextFocusableActor = window.GetRootLayer().FindChildById(actorId); + } } } } } - if( !nextFocusableActor ) + if(!nextFocusableActor) { // If the implementation of CustomAlgorithmInterface is provided then the PreFocusChangeSignal is no longer emitted. - if( mCustomAlgorithmInterface ) + if(mCustomAlgorithmInterface) { mIsWaitingKeyboardFocusChangeCommit = true; - nextFocusableActor = mCustomAlgorithmInterface->GetNextFocusableActor( currentFocusActor, Actor(), direction ); + nextFocusableActor = mCustomAlgorithmInterface->GetNextFocusableActor(currentFocusActor, Actor(), direction); mIsWaitingKeyboardFocusChangeCommit = false; } - else if( !mPreFocusChangeSignal.Empty() ) + else if(!mPreFocusChangeSignal.Empty()) { // Don't know how to move the focus further. The application needs to tell us which actor to move the focus to mIsWaitingKeyboardFocusChangeCommit = true; - nextFocusableActor = mPreFocusChangeSignal.Emit( currentFocusActor, Actor(), direction ); + nextFocusableActor = mPreFocusChangeSignal.Emit(currentFocusActor, Actor(), direction); mIsWaitingKeyboardFocusChangeCommit = false; } + else if(mEnableDefaultAlgorithm) + { + // We should find it among the actors nearby. + nextFocusableActor = Toolkit::FocusFinder::GetNearestFocusableActor(currentFocusActor, direction); + } } - if( nextFocusableActor && nextFocusableActor.IsKeyboardFocusable() ) + if(nextFocusableActor && nextFocusableActor.GetProperty(Actor::Property::KEYBOARD_FOCUSABLE)) { // Whether the next focusable actor is a layout control - if( IsLayoutControl( nextFocusableActor ) ) + if(IsLayoutControl(nextFocusableActor)) { // If so, move the focus inside it. - Toolkit::Control layoutControl = Toolkit::Control::DownCast( nextFocusableActor) ; - succeed = DoMoveFocusWithinLayoutControl( layoutControl, currentFocusActor, direction ); + Toolkit::Control layoutControl = Toolkit::Control::DownCast(nextFocusableActor); + succeed = DoMoveFocusWithinLayoutControl(layoutControl, currentFocusActor, direction); } else { // Otherwise, just set focus to the next focusable actor - succeed = SetCurrentFocusActor( nextFocusableActor ); + succeed = SetCurrentFocusActor(nextFocusableActor); } } } @@ -427,29 +528,29 @@ bool KeyboardFocusManager::MoveFocus(Toolkit::Control::KeyboardFocus::Direction bool KeyboardFocusManager::DoMoveFocusWithinLayoutControl(Toolkit::Control control, Actor actor, Toolkit::Control::KeyboardFocus::Direction direction) { // Ask the control for the next actor to focus - Actor nextFocusableActor = GetImplementation( control ).GetNextKeyboardFocusableActor(actor, direction, mFocusGroupLoopEnabled); + Actor nextFocusableActor = GetImplementation(control).GetNextKeyboardFocusableActor(actor, direction, mFocusGroupLoopEnabled); if(nextFocusableActor) { - if(!nextFocusableActor.IsKeyboardFocusable()) + if(!nextFocusableActor.GetProperty(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); } else { - Actor currentFocusActor = GetCurrentFocusActor(); + Actor currentFocusActor = GetCurrentFocusActor(); Actor committedFocusActor = nextFocusableActor; // We will try to move the focus to the actor. Emit a signal to notify the proposed actor to focus // Signal handler can check the proposed actor and return a different actor if it wishes. - if( !mPreFocusChangeSignal.Empty() ) + if(!mPreFocusChangeSignal.Empty()) { mIsWaitingKeyboardFocusChangeCommit = true; - committedFocusActor = mPreFocusChangeSignal.Emit(currentFocusActor, nextFocusableActor, direction); + committedFocusActor = mPreFocusChangeSignal.Emit(currentFocusActor, nextFocusableActor, direction); mIsWaitingKeyboardFocusChangeCommit = false; } - if (committedFocusActor && committedFocusActor.IsKeyboardFocusable()) + if(committedFocusActor && committedFocusActor.GetProperty(Actor::Property::KEYBOARD_FOCUSABLE)) { // Whether the commited focusable actor is a layout control if(IsLayoutControl(committedFocusActor)) @@ -466,7 +567,7 @@ bool KeyboardFocusManager::DoMoveFocusWithinLayoutControl(Toolkit::Control contr // If the application hasn't changed our proposed actor, we informs the layout control we will // move the focus to what the control returns. The control might wish to perform some actions // before the focus is actually moved. - GetImplementation( control ).OnKeyboardFocusChangeCommitted( committedFocusActor ); + GetImplementation(control).OnKeyboardFocusChangeCommitted(committedFocusActor); } return SetCurrentFocusActor(committedFocusActor); @@ -497,8 +598,8 @@ bool KeyboardFocusManager::DoMoveFocusToNextFocusGroup(bool forward) // If the current focus group has a parent layout control, we can probably automatically // move the focus to the next focus group in the forward or backward direction. Toolkit::Control::KeyboardFocus::Direction direction = forward ? Toolkit::Control::KeyboardFocus::RIGHT : Toolkit::Control::KeyboardFocus::LEFT; - succeed = DoMoveFocusWithinLayoutControl(parentLayoutControl, GetCurrentFocusActor(), direction); - parentLayoutControl = GetParentLayoutControl(parentLayoutControl); + succeed = DoMoveFocusWithinLayoutControl(parentLayoutControl, GetCurrentFocusActor(), direction); + parentLayoutControl = GetParentLayoutControl(parentLayoutControl); } if(!mFocusGroupChangedSignal.Empty()) @@ -512,19 +613,19 @@ bool KeyboardFocusManager::DoMoveFocusToNextFocusGroup(bool forward) void KeyboardFocusManager::DoKeyboardEnter(Actor actor) { - if( actor ) + if(actor) { - Toolkit::Control control = Toolkit::Control::DownCast( actor ); - if( control ) + Toolkit::Control control = Toolkit::Control::DownCast(actor); + if(control) { // Notify the control that enter has been pressed on it. - GetImplementation( control ).KeyboardEnter(); + GetImplementation(control).KeyboardEnter(); } // Send a notification for the actor. - if( !mFocusedActorEnterKeySignal.Empty() ) + if(!mFocusedActorEnterKeySignal.Empty()) { - mFocusedActorEnterKeySignal.Emit( actor ); + mFocusedActorEnterKeySignal.Emit(actor); } } } @@ -532,29 +633,29 @@ void KeyboardFocusManager::DoKeyboardEnter(Actor actor) void KeyboardFocusManager::ClearFocus() { Actor actor = GetCurrentFocusActor(); - if( actor ) + if(actor) { - if( mFocusIndicatorActor ) + if(mFocusIndicatorActor) { - actor.Remove( mFocusIndicatorActor ); + actor.Remove(mFocusIndicatorActor); } // Send notification for the change of focus actor - if( !mFocusChangedSignal.Empty() ) + if(!mFocusChangedSignal.Empty()) { - mFocusChangedSignal.Emit( actor, Actor() ); + mFocusChangedSignal.Emit(actor, Actor()); } - Toolkit::Control currentlyFocusedControl = Toolkit::Control::DownCast( actor ); - if( currentlyFocusedControl ) + Toolkit::Control currentlyFocusedControl = Toolkit::Control::DownCast(actor); + if(currentlyFocusedControl) { - currentlyFocusedControl.SetProperty( DevelControl::Property::STATE, DevelControl::NORMAL ); + currentlyFocusedControl.SetProperty(DevelControl::Property::STATE, DevelControl::NORMAL); currentlyFocusedControl.ClearKeyInputFocus(); } } mCurrentFocusActor.Reset(); - mIsFocusIndicatorEnabled = 0; + mIsFocusIndicatorShown = (mAlwaysShowIndicator == ALWAYS_SHOW) ? SHOW : HIDE; } void KeyboardFocusManager::SetFocusGroupLoop(bool enabled) @@ -572,7 +673,7 @@ void KeyboardFocusManager::SetAsFocusGroup(Actor actor, bool isFocusGroup) if(actor) { // Create/Set focus group property. - actor.RegisterProperty( IS_FOCUS_GROUP_PROPERTY_NAME, isFocusGroup, Property::READ_WRITE ); + actor.RegisterProperty(IS_FOCUS_GROUP_PROPERTY_NAME, isFocusGroup, Property::READ_WRITE); } } @@ -596,7 +697,7 @@ bool KeyboardFocusManager::IsFocusGroup(Actor actor) const Actor KeyboardFocusManager::GetFocusGroup(Actor actor) { // Go through the actor's hierarchy to check which focus group the actor belongs to - while (actor && !IsFocusGroup(actor)) + while(actor && !IsFocusGroup(actor)) { actor = actor.GetParent(); } @@ -629,48 +730,44 @@ void KeyboardFocusManager::SetFocusIndicatorActor(Actor indicator) Actor KeyboardFocusManager::GetFocusIndicatorActor() { - if( ! mFocusIndicatorActor ) + 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.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; } void KeyboardFocusManager::OnKeyEvent(const KeyEvent& event) { - AccessibilityAdaptor accessibilityAdaptor = AccessibilityAdaptor::Get(); - bool isAccessibilityEnabled = accessibilityAdaptor.IsEnabled(); - - Toolkit::AccessibilityManager accessibilityManager = Toolkit::AccessibilityManager::Get(); - - std::string keyName = event.keyPressedName; + std::string keyName = event.GetKeyName(); - if( mIsFocusIndicatorEnabled == -1 ) + if(mIsFocusIndicatorShown == UNKNOWN) { GetConfigurationFromStyleManger(); } bool isFocusStartableKey = false; - if(event.state == KeyEvent::Down) + if(event.GetState() == KeyEvent::DOWN) { - if (keyName == "Left") + if(keyName == "Left") { - if(!isAccessibilityEnabled) + if(!mIsFocusIndicatorShown) { - if(!mIsFocusIndicatorEnabled) + if(mIsFocusIndicatorShown == HIDE) { // Show focus indicator - mIsFocusIndicatorEnabled = 1; + mIsFocusIndicatorShown = SHOW; } else { @@ -682,18 +779,20 @@ void KeyboardFocusManager::OnKeyEvent(const KeyEvent& event) } else { - // Move the accessibility focus backward - accessibilityManager.MoveFocusBackward(); + // Move the focus towards left + MoveFocus(Toolkit::Control::KeyboardFocus::LEFT); } + + isFocusStartableKey = true; } - else if (keyName == "Right") + else if(keyName == "Right") { - if(!isAccessibilityEnabled) + if(!mIsFocusIndicatorShown) { - if(!mIsFocusIndicatorEnabled) + if(mIsFocusIndicatorShown == HIDE) { // Show focus indicator - mIsFocusIndicatorEnabled = 1; + mIsFocusIndicatorShown = SHOW; } else { @@ -703,18 +802,18 @@ void KeyboardFocusManager::OnKeyEvent(const KeyEvent& event) } else { - // Move the accessibility focus forward - accessibilityManager.MoveFocusForward(); + // Move the focus towards right + MoveFocus(Toolkit::Control::KeyboardFocus::RIGHT); } isFocusStartableKey = true; } - else if (keyName == "Up" && !isAccessibilityEnabled) + else if(keyName == "Up") { - if(!mIsFocusIndicatorEnabled) + if(mIsFocusIndicatorShown == HIDE) { // Show focus indicator - mIsFocusIndicatorEnabled = 1; + mIsFocusIndicatorShown = SHOW; } else { @@ -724,12 +823,12 @@ void KeyboardFocusManager::OnKeyEvent(const KeyEvent& event) isFocusStartableKey = true; } - else if (keyName == "Down" && !isAccessibilityEnabled) + else if(keyName == "Down") { - if(!mIsFocusIndicatorEnabled) + if(mIsFocusIndicatorShown == HIDE) { // Show focus indicator - mIsFocusIndicatorEnabled = 1; + mIsFocusIndicatorShown = SHOW; } else { @@ -739,12 +838,12 @@ void KeyboardFocusManager::OnKeyEvent(const KeyEvent& event) isFocusStartableKey = true; } - else if (keyName == "Prior" && !isAccessibilityEnabled) + else if(keyName == "Prior") { - if(!mIsFocusIndicatorEnabled) + if(mIsFocusIndicatorShown == HIDE) { // Show focus indicator - mIsFocusIndicatorEnabled = 1; + mIsFocusIndicatorShown = SHOW; } else { @@ -754,12 +853,12 @@ void KeyboardFocusManager::OnKeyEvent(const KeyEvent& event) isFocusStartableKey = true; } - else if (keyName == "Next" && !isAccessibilityEnabled) + else if(keyName == "Next") { - if(!mIsFocusIndicatorEnabled) + if(mIsFocusIndicatorShown == HIDE) { // Show focus indicator - mIsFocusIndicatorEnabled = 1; + mIsFocusIndicatorShown = SHOW; } else { @@ -769,76 +868,75 @@ void KeyboardFocusManager::OnKeyEvent(const KeyEvent& event) isFocusStartableKey = true; } - else if (keyName == "Tab" && !isAccessibilityEnabled) + else if(keyName == "Tab") { - if(!mIsFocusIndicatorEnabled) + if(mIsFocusIndicatorShown == HIDE) { // Show focus indicator - mIsFocusIndicatorEnabled = 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) + else if(keyName == "space") { - if(!mIsFocusIndicatorEnabled) + if(mIsFocusIndicatorShown == HIDE) { // Show focus indicator - mIsFocusIndicatorEnabled = 1; + mIsFocusIndicatorShown = SHOW; } isFocusStartableKey = true; } - else if (keyName == "" && !isAccessibilityEnabled) + else if(keyName == "") { // Check the fake key event for evas-plugin case - if(!mIsFocusIndicatorEnabled) + if(mIsFocusIndicatorShown == HIDE) { // Show focus indicator - mIsFocusIndicatorEnabled = 1; + mIsFocusIndicatorShown = SHOW; } isFocusStartableKey = true; } - else if (keyName == "Backspace" && !isAccessibilityEnabled) + else if(keyName == "Backspace") { // Emit signal to go back to the previous view??? } - else if (keyName == "Escape" && !isAccessibilityEnabled) + else if(keyName == "Escape") { } } - else if(event.state == KeyEvent::Up) + else if(event.GetState() == KeyEvent::UP) { - if (keyName == "Return") + if(keyName == "Return") { - if(!mIsFocusIndicatorEnabled && !isAccessibilityEnabled) + if(mIsFocusIndicatorShown == HIDE) { // Show focus indicator - mIsFocusIndicatorEnabled = 1; + mIsFocusIndicatorShown = SHOW; } else { // The focused actor has enter pressed on it - Actor actor; - if( !isAccessibilityEnabled ) + Actor actor = GetCurrentFocusActor(); + if(actor) { - actor = GetCurrentFocusActor(); - } - else - { - actor = accessibilityManager.GetCurrentFocusActor(); - } - - if( actor ) - { - DoKeyboardEnter( actor ); + DoKeyboardEnter(actor); } } @@ -846,13 +944,16 @@ void KeyboardFocusManager::OnKeyEvent(const KeyEvent& event) } } - if(isFocusStartableKey && mIsFocusIndicatorEnabled && !isAccessibilityEnabled) + if(isFocusStartableKey && mIsFocusIndicatorShown == SHOW) { Actor actor = GetCurrentFocusActor(); - if( actor ) + if(actor) { - // Make sure the focused actor is highlighted - actor.Add( GetFocusIndicatorActor() ); + if(mEnableFocusIndicator == ENABLE) + { + // Make sure the focused actor is highlighted + actor.Add(GetFocusIndicatorActor()); + } } else { @@ -863,21 +964,52 @@ void KeyboardFocusManager::OnKeyEvent(const KeyEvent& event) } } -void KeyboardFocusManager::OnTouch(const TouchData& touch) +void KeyboardFocusManager::OnTouch(const TouchEvent& touch) { - // if mIsFocusIndicatorEnabled is -1, it means Configuration is not loaded. + // if mIsFocusIndicatorShown is UNKNOWN, it means Configuration is not loaded. // Try to load configuration. - if( mIsFocusIndicatorEnabled == -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; + } } } @@ -901,28 +1033,28 @@ Toolkit::KeyboardFocusManager::FocusedActorEnterKeySignalType& KeyboardFocusMana return mFocusedActorEnterKeySignal; } -bool KeyboardFocusManager::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor ) +bool KeyboardFocusManager::DoConnectSignal(BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor) { - Dali::BaseHandle handle( object ); + Dali::BaseHandle handle(object); - bool connected( true ); - KeyboardFocusManager* manager = static_cast< KeyboardFocusManager* >( object ); // TypeRegistry guarantees that this is the correct type. + bool connected(true); + KeyboardFocusManager* manager = static_cast(object); // TypeRegistry guarantees that this is the correct type. - if( 0 == strcmp( signalName.c_str(), SIGNAL_PRE_FOCUS_CHANGE ) ) + if(0 == strcmp(signalName.c_str(), SIGNAL_PRE_FOCUS_CHANGE)) { - manager->PreFocusChangeSignal().Connect( tracker, functor ); + manager->PreFocusChangeSignal().Connect(tracker, functor); } - else if( 0 == strcmp( signalName.c_str(), SIGNAL_FOCUS_CHANGED ) ) + else if(0 == strcmp(signalName.c_str(), SIGNAL_FOCUS_CHANGED)) { - manager->FocusChangedSignal().Connect( tracker, functor ); + manager->FocusChangedSignal().Connect(tracker, functor); } - else if( 0 == strcmp( signalName.c_str(), SIGNAL_FOCUS_GROUP_CHANGED ) ) + else if(0 == strcmp(signalName.c_str(), SIGNAL_FOCUS_GROUP_CHANGED)) { - manager->FocusGroupChangedSignal().Connect( tracker, functor ); + manager->FocusGroupChangedSignal().Connect(tracker, functor); } - else if( 0 == strcmp( signalName.c_str(), SIGNAL_FOCUSED_ACTOR_ENTER_KEY ) ) + else if(0 == strcmp(signalName.c_str(), SIGNAL_FOCUSED_ACTOR_ENTER_KEY)) { - manager->FocusedActorEnterKeySignal().Connect( tracker, functor ); + manager->FocusedActorEnterKeySignal().Connect(tracker, functor); } else { @@ -938,6 +1070,31 @@ void KeyboardFocusManager::SetCustomAlgorithm(CustomAlgorithmInterface& interfac mCustomAlgorithmInterface = &interface; } +void KeyboardFocusManager::EnableFocusIndicator(bool enable) +{ + if(!enable && mFocusIndicatorActor) + { + mFocusIndicatorActor.Unparent(); + } + + mEnableFocusIndicator = enable ? ENABLE : DISABLE; +} + +bool KeyboardFocusManager::IsFocusIndicatorEnabled() const +{ + return (mEnableFocusIndicator == ENABLE); +} + +void KeyboardFocusManager::EnableDefaultAlgorithm(bool enable) +{ + mEnableDefaultAlgorithm = enable; +} + +bool KeyboardFocusManager::IsDefaultAlgorithmEnabled() const +{ + return mEnableDefaultAlgorithm; +} + } // namespace Internal } // namespace Toolkit