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=197550fff616dcbe8ccecff4a98ec581319ae6a5;hp=5be38acdd6afcbea7806c7177fe9b679f60ed38f;hb=770caa74d30341ac8e8c4ec81736a768077aa5b3;hpb=64cacc4d250a25eb19c27ed55741f3ae61266518 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 5be38ac..197550f 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) 2014 Samsung Electronics Co., Ltd. + * Copyright (c) 2016 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,20 +21,22 @@ // EXTERNAL INCLUDES #include // for strcmp #include -#include +#include #include #include #include #include +#include #include -#include +#include #include #include // INTERNAL INCLUDES #include #include -#include +#include +#include #include namespace Dali @@ -53,10 +55,9 @@ namespace // Unnamed namespace Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_KEYBOARD_FOCUS_MANAGER"); #endif -const char* const IS_FOCUS_GROUP_PROPERTY_NAME = "is-keyboard-focus-group"; // This property will be replaced by a flag in Control. +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.png"; -const Vector4 FOCUS_BORDER_IMAGE_BORDER = Vector4(7.0f, 7.0f, 7.0f, 7.0f); +const char* const FOCUS_BORDER_IMAGE_PATH = DALI_IMAGE_DIR "keyboard_focus.9.png"; BaseHandle Create() { @@ -78,13 +79,15 @@ BaseHandle Create() DALI_TYPE_REGISTRATION_BEGIN_CREATE( Toolkit::KeyboardFocusManager, Dali::BaseHandle, Create, true ) -DALI_SIGNAL_REGISTRATION( Toolkit, KeyboardFocusManager, "keyboard-pre-focus-change", SIGNAL_PRE_FOCUS_CHANGE ) -DALI_SIGNAL_REGISTRATION( Toolkit, KeyboardFocusManager, "keyboard-focus-changed", SIGNAL_FOCUS_CHANGED ) -DALI_SIGNAL_REGISTRATION( Toolkit, KeyboardFocusManager, "keyboard-focus-group-changed", SIGNAL_FOCUS_GROUP_CHANGED ) -DALI_SIGNAL_REGISTRATION( Toolkit, KeyboardFocusManager, "keyboard-focused-actor-activated", SIGNAL_FOCUSED_ACTOR_ACTIVATED ) +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() +const unsigned int MAX_HISTORY_AMOUNT = 30; ///< Max length of focus history stack + } // unnamed namespace Toolkit::KeyboardFocusManager KeyboardFocusManager::Get() @@ -107,20 +110,23 @@ Toolkit::KeyboardFocusManager KeyboardFocusManager::Get() } KeyboardFocusManager::KeyboardFocusManager() -: mCurrentFocusActor(0), - mFocusIndicatorActor(Actor()), - mFocusGroupLoopEnabled(false), - mIsKeyboardFocusEnabled(false), - mIsFocusIndicatorEnabled(false), - mIsWaitingKeyboardFocusChangeCommit(false), - mSlotDelegate(this) +: mPreFocusChangeSignal(), + mFocusChangedSignal(), + mFocusGroupChangedSignal(), + mFocusedActorEnterKeySignal(), + mCurrentFocusActor( 0 ), + mFocusIndicatorActor(), + mFocusGroupLoopEnabled( false ), + mIsKeyboardFocusEnabled( false ), + mIsFocusIndicatorEnabled( false ), + mIsWaitingKeyboardFocusChangeCommit( false ), + mFocusHistory(), + mSlotDelegate( this ) { - CreateDefaultFocusIndicatorActor(); - OnPhysicalKeyboardStatusChanged(PhysicalKeyboard::Get()); Toolkit::KeyInputFocusManager::Get().UnhandledKeyEventSignal().Connect(mSlotDelegate, &KeyboardFocusManager::OnKeyEvent); - Stage::GetCurrent().TouchedSignal().Connect(mSlotDelegate, &KeyboardFocusManager::OnTouched); + Stage::GetCurrent().TouchSignal().Connect( mSlotDelegate, &KeyboardFocusManager::OnTouch ); PhysicalKeyboard::Get().StatusChangedSignal().Connect(mSlotDelegate, &KeyboardFocusManager::OnPhysicalKeyboardStatusChanged); } @@ -128,53 +134,63 @@ KeyboardFocusManager::~KeyboardFocusManager() { } -bool KeyboardFocusManager::SetCurrentFocusActor(Actor actor) +bool KeyboardFocusManager::SetCurrentFocusActor( Actor actor ) { DALI_ASSERT_DEBUG( !mIsWaitingKeyboardFocusChangeCommit && "Calling this function in the PreFocusChangeSignal callback?" ); - if(actor) + if( actor ) { - return DoSetCurrentFocusActor(actor.GetId()); + return DoSetCurrentFocusActor( actor.GetId() ); } return false; } -bool KeyboardFocusManager::DoSetCurrentFocusActor(const unsigned int actorID) +bool KeyboardFocusManager::DoSetCurrentFocusActor( const unsigned int actorID ) { Actor rootActor = Stage::GetCurrent().GetRootLayer(); - Actor actor = rootActor.FindChildById(actorID); + Actor actor = rootActor.FindChildById( actorID ); + bool success = false; - // Check whether the actor is in the stage - if(actor) + // Check whether the actor is in the stage and is keyboard focusable. + if( actor && actor.IsKeyboardFocusable() ) { - // Set the focus only when the actor is keyboard focusable - if(actor.IsKeyboardFocusable()) + mIsFocusIndicatorEnabled = true; + // Draw the focus indicator upon the focused actor when PhysicalKeyboard is attached + if( mIsKeyboardFocusEnabled ) { - // Draw the focus indicator upon the focused actor - if(mIsFocusIndicatorEnabled && mFocusIndicatorActor) - { - actor.Add(mFocusIndicatorActor); - } + actor.Add( GetFocusIndicatorActor() ); + } + // Send notification for the change of focus actor + if( !mFocusChangedSignal.Empty() ) + { + mFocusChangedSignal.Emit(GetCurrentFocusActor(), actor); + } - // Send notification for the change of focus actor - if( !mFocusChangedSignal.Empty() ) - { - mFocusChangedSignal.Emit(GetCurrentFocusActor(), actor); - } + 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 = actorID; - // Save the current focused actor - mCurrentFocusActor = actorID; + // Push Current Focused Actor to FocusHistory + mFocusHistory.PushBack( &actor.GetBaseObject() ); - DALI_LOG_INFO( gLogFilter, Debug::General, "[%s:%d] SUCCEED\n", __FUNCTION__, __LINE__); - return true; + // Delete first element before add new element when Stack is full. + if( mFocusHistory.Count() > MAX_HISTORY_AMOUNT ) + { + FocusStackIterator beginPos = mFocusHistory.Begin(); + mFocusHistory.Erase( beginPos ); } + + DALI_LOG_INFO( gLogFilter, Debug::General, "[%s:%d] SUCCEED\n", __FUNCTION__, __LINE__); + success = true; + } + else + { + DALI_LOG_WARNING("[%s:%d] FAILED\n", __FUNCTION__, __LINE__); } - DALI_LOG_WARNING("[%s:%d] FAILED\n", __FUNCTION__, __LINE__); - return false; + return success; } Actor KeyboardFocusManager::GetCurrentFocusActor() @@ -188,6 +204,33 @@ Actor KeyboardFocusManager::GetCurrentFocusGroup() return GetFocusGroup(GetCurrentFocusActor()); } +void KeyboardFocusManager::MoveFocusBackward() +{ + // Find Pre Focused Actor when the list size is more than 1 + if( mFocusHistory.Count() > 1 ) + { + // Delete current focused actor in history + FocusStackIterator endPos = mFocusHistory.End(); + endPos = mFocusHistory.Erase( --endPos ); + + // If pre-focused actors are not on stage, remove them in stack + while( !Dali::Actor::DownCast(BaseHandle(mFocusHistory[ mFocusHistory.Count() - 1 ])).OnStage() ) + { + endPos = mFocusHistory.Erase( --endPos ); + } + + // Get pre focused actor + BaseObject* object = mFocusHistory[ mFocusHistory.Count() - 1 ]; + BaseHandle handle( object ); + Actor preFocusedActor = Dali::Actor::DownCast( handle ); + + // Delete pre focused actor in history because it will pushed again by SetCurrentFocusActor() + mFocusHistory.Erase( --endPos ); + + SetCurrentFocusActor( preFocusedActor ); + } +} + bool KeyboardFocusManager::IsLayoutControl(Actor actor) const { Toolkit::Control control = Toolkit::Control::DownCast(actor); @@ -339,21 +382,21 @@ bool KeyboardFocusManager::DoMoveFocusToNextFocusGroup(bool forward) return succeed; } -void KeyboardFocusManager::DoActivate(Actor actor) +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 it is activated - GetImplementation( control ).AccessibilityActivate(); + // Notify the control that enter has been pressed on it. + GetImplementation( control ).KeyboardEnter(); } - // Send notification for the activation of focused actor - if( !mFocusedActorActivatedSignal.Empty() ) + // Send a notification for the actor. + if( !mFocusedActorEnterKeySignal.Empty() ) { - mFocusedActorActivatedSignal.Emit(actor); + mFocusedActorEnterKeySignal.Emit( actor ); } } } @@ -393,16 +436,8 @@ void KeyboardFocusManager::SetAsFocusGroup(Actor actor, bool isFocusGroup) { if(actor) { - // Create focus group property if not already created. - Property::Index propertyIsFocusGroup = actor.GetPropertyIndex(IS_FOCUS_GROUP_PROPERTY_NAME); - if(propertyIsFocusGroup == Property::INVALID_INDEX) - { - actor.RegisterProperty(IS_FOCUS_GROUP_PROPERTY_NAME, isFocusGroup, Property::READ_WRITE ); - } - else - { - actor.SetProperty(propertyIsFocusGroup, isFocusGroup); - } + // Create/Set focus group property. + actor.RegisterProperty( IS_FOCUS_GROUP_PROPERTY_NAME, isFocusGroup, Property::READ_WRITE ); } } @@ -459,24 +494,17 @@ void KeyboardFocusManager::SetFocusIndicatorActor(Actor indicator) Actor KeyboardFocusManager::GetFocusIndicatorActor() { - return mFocusIndicatorActor; -} - -void KeyboardFocusManager::CreateDefaultFocusIndicatorActor() -{ - // Create a focus indicator actor shared by all the keyboard focusable actors - Image borderImage = ResourceImage::New(FOCUS_BORDER_IMAGE_PATH); - - ImageActor focusIndicator = ImageActor::New(borderImage); - focusIndicator.SetPositionInheritanceMode( Dali::USE_PARENT_POSITION_PLUS_LOCAL_POSITION ); - focusIndicator.SetStyle( ImageActor::STYLE_NINE_PATCH ); - focusIndicator.SetNinePatchBorder(FOCUS_BORDER_IMAGE_BORDER); - focusIndicator.SetPosition(Vector3(0.0f, 0.0f, 1.0f)); + 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 ); + mFocusIndicatorActor.SetParentOrigin( ParentOrigin::CENTER ); - // Apply size constraint to the focus indicator - focusIndicator.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS ); + // Apply size constraint to the focus indicator + mFocusIndicatorActor.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS ); + } - SetFocusIndicatorActor(focusIndicator); + return mFocusIndicatorActor; } void KeyboardFocusManager::OnPhysicalKeyboardStatusChanged(PhysicalKeyboard keyboard) @@ -489,10 +517,7 @@ void KeyboardFocusManager::OnPhysicalKeyboardStatusChanged(PhysicalKeyboard keyb Actor actor = GetCurrentFocusActor(); if(actor) { - if(mFocusIndicatorActor) - { - actor.Add(mFocusIndicatorActor); - } + actor.Add( GetFocusIndicatorActor() ); } mIsFocusIndicatorEnabled = true; } @@ -500,9 +525,9 @@ void KeyboardFocusManager::OnPhysicalKeyboardStatusChanged(PhysicalKeyboard keyb { // Hide indicator when keyboard focus turned off Actor actor = GetCurrentFocusActor(); - if(actor) + if( actor && mFocusIndicatorActor ) { - actor.Remove(mFocusIndicatorActor); + actor.Remove( mFocusIndicatorActor ); } mIsFocusIndicatorEnabled = false; } @@ -515,10 +540,10 @@ void KeyboardFocusManager::OnKeyEvent(const KeyEvent& event) return; } - AccessibilityManager accessibilityManager = AccessibilityManager::Get(); - bool isAccessibilityEnabled = accessibilityManager.IsEnabled(); + AccessibilityAdaptor accessibilityAdaptor = AccessibilityAdaptor::Get(); + bool isAccessibilityEnabled = accessibilityAdaptor.IsEnabled(); - Toolkit::AccessibilityFocusManager accessibilityFocusManager = Toolkit::AccessibilityFocusManager::Get(); + Toolkit::AccessibilityManager accessibilityManager = Toolkit::AccessibilityManager::Get(); std::string keyName = event.keyPressedName; @@ -546,7 +571,7 @@ void KeyboardFocusManager::OnKeyEvent(const KeyEvent& event) else { // Move the accessibility focus backward - accessibilityFocusManager.MoveFocusBackward(); + accessibilityManager.MoveFocusBackward(); } } else if (keyName == "Right") @@ -567,7 +592,7 @@ void KeyboardFocusManager::OnKeyEvent(const KeyEvent& event) else { // Move the accessibility focus forward - accessibilityFocusManager.MoveFocusForward(); + accessibilityManager.MoveFocusForward(); } isFocusStartableKey = true; @@ -602,6 +627,36 @@ void KeyboardFocusManager::OnKeyEvent(const KeyEvent& event) isFocusStartableKey = true; } + else if (keyName == "Prior" && !isAccessibilityEnabled) + { + if(!mIsFocusIndicatorEnabled) + { + // Show focus indicator + mIsFocusIndicatorEnabled = true; + } + else + { + // Move the focus towards the previous page + MoveFocus(Toolkit::Control::KeyboardFocus::PAGE_UP); + } + + isFocusStartableKey = true; + } + else if (keyName == "Next" && !isAccessibilityEnabled) + { + if(!mIsFocusIndicatorEnabled) + { + // Show focus indicator + mIsFocusIndicatorEnabled = true; + } + else + { + // Move the focus towards the next page + MoveFocus(Toolkit::Control::KeyboardFocus::PAGE_DOWN); + } + + isFocusStartableKey = true; + } else if (keyName == "Tab" && !isAccessibilityEnabled) { if(!mIsFocusIndicatorEnabled) @@ -643,6 +698,9 @@ void KeyboardFocusManager::OnKeyEvent(const KeyEvent& event) { // Emit signal to go back to the previous view??? } + else if (keyName == "Escape" && !isAccessibilityEnabled) + { + } } else if(event.state == KeyEvent::Up) { @@ -655,20 +713,20 @@ void KeyboardFocusManager::OnKeyEvent(const KeyEvent& event) } else { - // Activate the focused actor + // The focused actor has enter pressed on it Actor actor; - if(!isAccessibilityEnabled) + if( !isAccessibilityEnabled ) { actor = GetCurrentFocusActor(); } else { - actor = accessibilityFocusManager.GetCurrentFocusActor(); + actor = accessibilityManager.GetCurrentFocusActor(); } - if(actor) + if( actor ) { - DoActivate(actor); + DoKeyboardEnter( actor ); } } @@ -679,24 +737,28 @@ void KeyboardFocusManager::OnKeyEvent(const KeyEvent& event) if(isFocusStartableKey && mIsFocusIndicatorEnabled && !isAccessibilityEnabled) { Actor actor = GetCurrentFocusActor(); - if( !actor ) + if( actor ) + { + // Make sure the focused actor is highlighted + actor.Add( GetFocusIndicatorActor() ); + } + else { // No actor is focused but keyboard focus is activated by the key press // Let's try to move the initial focus MoveFocus(Toolkit::Control::KeyboardFocus::RIGHT); } - else if(mFocusIndicatorActor) - { - // Make sure the focused actor is highlighted - actor.Add(mFocusIndicatorActor); - } } } -void KeyboardFocusManager::OnTouched(const TouchEvent& touchEvent) +void KeyboardFocusManager::OnTouch(const TouchData& touch) { - // Clear the focus when user touch the screen - ClearFocus(); + // 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( ( touch.GetPointCount() < 1 ) || ( touch.GetState( 0 ) == PointState::DOWN ) ) + { + ClearFocus(); + } } Toolkit::KeyboardFocusManager::PreFocusChangeSignalType& KeyboardFocusManager::PreFocusChangeSignal() @@ -714,9 +776,9 @@ Toolkit::KeyboardFocusManager::FocusGroupChangedSignalType& KeyboardFocusManager return mFocusGroupChangedSignal; } -Toolkit::KeyboardFocusManager::FocusedActorActivatedSignalType& KeyboardFocusManager::FocusedActorActivatedSignal() +Toolkit::KeyboardFocusManager::FocusedActorEnterKeySignalType& KeyboardFocusManager::FocusedActorEnterKeySignal() { - return mFocusedActorActivatedSignal; + return mFocusedActorEnterKeySignal; } bool KeyboardFocusManager::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor ) @@ -724,23 +786,23 @@ bool KeyboardFocusManager::DoConnectSignal( BaseObject* object, ConnectionTracke Dali::BaseHandle handle( object ); bool connected( true ); - KeyboardFocusManager* manager = dynamic_cast( object ); + KeyboardFocusManager* manager = static_cast< KeyboardFocusManager* >( object ); // TypeRegistry guarantees that this is the correct type. if( 0 == strcmp( signalName.c_str(), SIGNAL_PRE_FOCUS_CHANGE ) ) { manager->PreFocusChangeSignal().Connect( tracker, functor ); } - if( 0 == strcmp( signalName.c_str(), SIGNAL_FOCUS_CHANGED ) ) + else if( 0 == strcmp( signalName.c_str(), SIGNAL_FOCUS_CHANGED ) ) { manager->FocusChangedSignal().Connect( tracker, functor ); } - 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 ); } - else if( 0 == strcmp( signalName.c_str(), SIGNAL_FOCUSED_ACTOR_ACTIVATED ) ) + else if( 0 == strcmp( signalName.c_str(), SIGNAL_FOCUSED_ACTOR_ENTER_KEY ) ) { - manager->FocusedActorActivatedSignal().Connect( tracker, functor ); + manager->FocusedActorEnterKeySignal().Connect( tracker, functor ); } else {