Hover events are a collection of touch points at a specific moment in time.
When a multi-touch event occurs, each touch point represents the points that
are currently being hovered or the points where a hover has stopped.
Hover event processor processes hover events and emits the Hovered signal
on the hit actor (and its parents).
Change-Id: Ife8e7c1561158e8f98061eb5037ad3b6944846dd
#include <dali/public-api/dali-core.h>
#include <dali/integration-api/events/touch-event-integ.h>
+#include <dali/integration-api/events/hover-event-integ.h>
#include <dali/integration-api/events/mouse-wheel-event-integ.h>
#include <dali/integration-api/events/key-event-integ.h>
AddToCallStacks("OnTouchEvent");
return true;
}
+ virtual bool OnHoverEvent(const HoverEvent& event)
+ {
+ AddToCallStacks("OnHoverEvent");
+ return true;
+ }
virtual bool OnMouseWheelEvent(const MouseWheelEvent& event)
{
AddToCallStacks("OnMouseWheelEvent");
#include <dali/integration-api/events/pinch-gesture-event.h>
#include <dali/integration-api/events/tap-gesture-event.h>
#include <dali/integration-api/events/touch-event-integ.h>
+#include <dali/integration-api/events/hover-event-integ.h>
using namespace Dali;
{
return true;
}
+ virtual bool OnHoverEvent(const HoverEvent& event)
+ {
+ return true;
+ }
virtual bool OnMouseWheelEvent(const MouseWheelEvent& event)
{
return true;
utc-Dali-Gesture.cpp
utc-Dali-GestureDetector.cpp
utc-Dali-Handle.cpp
+ utc-Dali-HoverProcessing.cpp
utc-Dali-Image.cpp
utc-Dali-ImageActor.cpp
utc-Dali-ImageAttributes.cpp
#include <dali/public-api/dali-core.h>
#include <string>
#include <dali/integration-api/events/touch-event-integ.h>
+#include <dali/integration-api/events/hover-event-integ.h>
#include <dali-test-suite-utils.h>
//& set: DaliActor
bool gTouchCallBackCalled=false;
bool gTouchCallBack2Called=false;
+bool gHoverCallBackCalled=false;
/**
* Simulates a Down Touch at 25.0, 25.0.
END_TEST;
}
+static bool TestCallback3(Actor actor, const HoverEvent& event)
+{
+ gHoverCallBackCalled = true;
+ return false;
+ END_TEST;
+}
+
static Vector3 gSetSize;
static bool gSetSizeCallBackCalled;
void SetSizeCallback( Actor actor, const Vector3& size )
END_TEST;
}
+int UtcDaliActorHoveredSignal(void)
+{
+ TestApplication application;
+
+ gHoverCallBackCalled = false;
+
+ // get the root layer
+ Actor actor = Stage::GetCurrent().GetRootLayer();
+ DALI_TEST_CHECK( gHoverCallBackCalled == false );
+
+ application.SendNotification();
+ application.Render();
+
+ // connect to its hover signal
+ actor.HoveredSignal().Connect( TestCallback3 );
+
+ // simulate a hover event in the middle of the screen
+ Vector2 touchPoint( Stage::GetCurrent().GetSize() * 0.5 );
+ Dali::TouchPoint point( 1, TouchPoint::Motion, touchPoint.x, touchPoint.y );
+ Dali::Integration::HoverEvent event;
+ event.AddPoint( point );
+ application.ProcessEvent( event );
+
+ DALI_TEST_CHECK( gHoverCallBackCalled == true );
+ END_TEST;
+}
int UtcDaliActorSetSizeSignal(void)
{
#include <dali/public-api/dali-core.h>
#include <dali/integration-api/events/touch-event-integ.h>
+#include <dali/integration-api/events/hover-event-integ.h>
#include <dali/integration-api/events/mouse-wheel-event-integ.h>
#include <dali/integration-api/events/key-event-integ.h>
mTargetSize( Vector3::ZERO )
{
SetRequiresMouseWheelEvents(true);
+ SetRequiresHoverEvents(true);
}
/**
AddToCallStacks("OnTouchEvent");
return true;
}
+ virtual bool OnHoverEvent(const HoverEvent& event)
+ {
+ AddToCallStacks("OnHoverEvent");
+ return true;
+ }
virtual bool OnMouseWheelEvent(const MouseWheelEvent& event)
{
AddToCallStacks("OnMouseWheelEvent");
{
return true;
}
+ virtual bool OnHoverEvent(const HoverEvent& event)
+ {
+ return true;
+ }
virtual bool OnMouseWheelEvent(const MouseWheelEvent& event)
{
return true;
END_TEST;
}
+int UtcDaliCustomActorOnHoverEvent(void)
+{
+ TestApplication application;
+ tet_infoline("Testing Dali::CustomActor::OnHoverEvent()");
+
+ TestCustomActor custom = TestCustomActor::New();
+ DALI_TEST_EQUALS( 0, (int)(custom.GetMethodsCalled().size()), TEST_LOCATION );
+
+ // set size for custom actor
+ custom.SetSize( 100, 100 );
+ // add the custom actor to stage
+ Stage::GetCurrent().Add( custom );
+ custom.ResetCallStack();
+
+ // Render and notify a couple of times
+ application.SendNotification();
+ application.Render();
+ application.SendNotification();
+ application.Render();
+
+ // simulate a hover event
+ Dali::TouchPoint point( 0, TouchPoint::Motion, 1, 1 );
+ Dali::Integration::HoverEvent event;
+ event.AddPoint( point );
+ application.ProcessEvent( event );
+
+ DALI_TEST_EQUALS( 1, (int)(custom.GetMethodsCalled().size()), TEST_LOCATION );
+ DALI_TEST_EQUALS( "OnHoverEvent", custom.GetMethodsCalled()[ 0 ], TEST_LOCATION );
+ END_TEST;
+}
+
int UtcDaliCustomActorOnMouseWheelEvent(void)
{
TestApplication application;
--- /dev/null
+/*
+ * Copyright (c) 2014 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <iostream>
+
+#include <stdlib.h>
+#include <dali/public-api/dali-core.h>
+#include <dali/integration-api/events/hover-event-integ.h>
+#include <dali/integration-api/system-overlay.h>
+#include <dali-test-suite-utils.h>
+
+using namespace Dali;
+
+void utc_dali_hover_processing_startup(void)
+{
+ test_return_value = TET_UNDEF;
+}
+
+void utc_dali_hover_processing_cleanup(void)
+{
+ test_return_value = TET_PASS;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+namespace
+{
+
+// Stores data that is populated in the callback and will be read by the TET cases
+struct SignalData
+{
+ SignalData()
+ : functorCalled( false ),
+ hoverEvent(),
+ hoveredActor()
+ {
+ }
+
+ void Reset()
+ {
+ functorCalled = false;
+
+ hoverEvent.time = 0u;
+ hoverEvent.points.clear();
+
+ hoveredActor = NULL;
+ }
+
+ bool functorCalled;
+ HoverEvent hoverEvent;
+ Actor hoveredActor;
+};
+
+// Functor that sets the data when called
+struct HoverEventFunctor
+{
+ /**
+ * Constructor.
+ * @param[in] data Reference to the data to store callback information.
+ * @param[in] returnValue What the functor should return.
+ */
+ HoverEventFunctor( SignalData& data, bool returnValue = true )
+ : signalData( data ),
+ returnValue( returnValue )
+ {
+ }
+
+ bool operator()( Actor actor, const HoverEvent& hoverEvent )
+ {
+ signalData.functorCalled = true;
+ signalData.hoveredActor = actor;
+ signalData.hoverEvent = hoverEvent;
+
+ return returnValue;
+ }
+
+ SignalData& signalData;
+ bool returnValue;
+};
+
+// Functor that removes the actor when called.
+struct RemoveActorFunctor : public HoverEventFunctor
+{
+ /**
+ * Constructor.
+ * @param[in] data Reference to the data to store callback information.
+ * @param[in] returnValue What the functor should return.
+ */
+ RemoveActorFunctor( SignalData& data, bool returnValue = true )
+ : HoverEventFunctor( data, returnValue )
+ {
+ }
+
+ bool operator()( Actor actor, const HoverEvent& hoverEvent )
+ {
+ Actor parent( actor.GetParent() );
+ if ( parent )
+ {
+ parent.Remove( actor );
+ }
+
+ return HoverEventFunctor::operator()( actor, hoverEvent );
+ }
+};
+
+Integration::HoverEvent GenerateSingleHover( TouchPoint::State state, Vector2 screenPosition )
+{
+ Integration::HoverEvent hoverEvent;
+ hoverEvent.points.push_back( TouchPoint ( 0, state, screenPosition.x, screenPosition.y ) );
+ return hoverEvent;
+}
+
+} // anon namespace
+
+///////////////////////////////////////////////////////////////////////////////
+
+int UtcDaliHoverNormalProcessing(void)
+{
+ TestApplication application;
+
+ Actor actor = Actor::New();
+ actor.SetSize(100.0f, 100.0f);
+ actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+ Stage::GetCurrent().Add(actor);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Connect to actor's hovered signal
+ SignalData data;
+ HoverEventFunctor functor( data );
+ actor.HoveredSignal().Connect( &application, functor );
+
+ Vector2 screenCoordinates( 10.0f, 10.0f );
+ Vector2 localCoordinates;
+ actor.ScreenToLocal( localCoordinates.x, localCoordinates.y, screenCoordinates.x, screenCoordinates.y );
+
+ // Emit a started signal
+ application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, screenCoordinates ) );
+ DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+ DALI_TEST_EQUALS( 1u, data.hoverEvent.GetPointCount(), TEST_LOCATION );
+ DALI_TEST_EQUALS( TouchPoint::Started, data.hoverEvent.points[0].state, TEST_LOCATION );
+ DALI_TEST_EQUALS( screenCoordinates, data.hoverEvent.points[0].screen, TEST_LOCATION );
+ DALI_TEST_EQUALS( localCoordinates, data.hoverEvent.points[0].local, 0.1f, TEST_LOCATION );
+ data.Reset();
+
+ // Emit a motion signal
+ screenCoordinates.x = screenCoordinates.y = 11.0f;
+ actor.ScreenToLocal( localCoordinates.x, localCoordinates.y, screenCoordinates.x, screenCoordinates.y );
+ application.ProcessEvent( GenerateSingleHover( TouchPoint::Motion, screenCoordinates ) );
+ DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+ DALI_TEST_EQUALS( 1u, data.hoverEvent.GetPointCount(), TEST_LOCATION );
+ DALI_TEST_EQUALS( TouchPoint::Motion, data.hoverEvent.points[0].state, TEST_LOCATION );
+ DALI_TEST_EQUALS( screenCoordinates, data.hoverEvent.points[0].screen, TEST_LOCATION );
+ DALI_TEST_EQUALS( localCoordinates, data.hoverEvent.points[0].local, 0.1f, TEST_LOCATION );
+ data.Reset();
+
+ // Emit a finished signal
+ screenCoordinates.x = screenCoordinates.y = 12.0f;
+ actor.ScreenToLocal( localCoordinates.x, localCoordinates.y, screenCoordinates.x, screenCoordinates.y );
+ application.ProcessEvent( GenerateSingleHover( TouchPoint::Finished, screenCoordinates ) );
+ DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+ DALI_TEST_EQUALS( 1u, data.hoverEvent.GetPointCount(), TEST_LOCATION );
+ DALI_TEST_EQUALS( TouchPoint::Finished, data.hoverEvent.points[0].state, TEST_LOCATION );
+ DALI_TEST_EQUALS( screenCoordinates, data.hoverEvent.points[0].screen, TEST_LOCATION );
+ DALI_TEST_EQUALS( localCoordinates, data.hoverEvent.points[0].local, 0.1f, TEST_LOCATION );
+ data.Reset();
+
+ // Emit a started signal where the actor is not present
+ screenCoordinates.x = screenCoordinates.y = 200.0f;
+ application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, screenCoordinates ) );
+ DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION );
+ END_TEST;
+}
+
+int UtcDaliHoverOutsideCameraNearFarPlanes(void)
+{
+ TestApplication application;
+
+ Stage stage = Stage::GetCurrent();
+ Vector2 stageSize = stage.GetSize();
+
+ Actor actor = Actor::New();
+ actor.SetSize(100.0f, 100.0f);
+ actor.SetAnchorPoint(AnchorPoint::CENTER);
+ actor.SetParentOrigin(ParentOrigin::CENTER);
+ stage.Add(actor);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Get the camera's near and far planes
+ RenderTaskList taskList = stage.GetRenderTaskList();
+ Dali::RenderTask task = taskList.GetTask(0);
+ CameraActor camera = task.GetCameraActor();
+ float nearPlane = camera.GetNearClippingPlane();
+ float farPlane = camera.GetFarClippingPlane();
+
+ // Calculate the current distance of the actor from the camera
+ float tanHalfFov = tanf(camera.GetFieldOfView() * 0.5f);
+ float distance = (stageSize.y * 0.5f) / tanHalfFov;
+
+ // Connect to actor's hovered signal
+ SignalData data;
+ HoverEventFunctor functor( data );
+ actor.HoveredSignal().Connect( &application, functor );
+
+ Vector2 screenCoordinates( stageSize.x * 0.5f, stageSize.y * 0.5f );
+
+ // Emit a started signal
+ application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, screenCoordinates ) );
+ DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+ data.Reset();
+
+ // Emit a started signal where actor is just at the camera's near plane
+ actor.SetZ(distance - nearPlane);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, screenCoordinates ) );
+ DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+ data.Reset();
+
+ // Emit a started signal where actor is closer than the camera's near plane
+ actor.SetZ((distance - nearPlane) + 1.0f);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, screenCoordinates ) );
+ DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION );
+ data.Reset();
+
+ // Emit a started signal where actor is just at the camera's far plane
+ actor.SetZ(distance - farPlane);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, screenCoordinates ) );
+ DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+ data.Reset();
+
+ // Emit a started signal where actor is further than the camera's far plane
+ actor.SetZ((distance - farPlane) - 1.0f);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, screenCoordinates ) );
+ DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION );
+ data.Reset();
+ END_TEST;
+}
+
+int UtcDaliHoverEmitEmpty(void)
+{
+ TestApplication application;
+
+ try
+ {
+ // Emit an empty HoverEvent
+ Integration::HoverEvent event;
+ application.ProcessEvent( event );
+ tet_result( TET_FAIL );
+ }
+ catch ( Dali::DaliException& e )
+ {
+ DALI_TEST_ASSERT( e, "!event.points.empty()", TEST_LOCATION );
+ }
+ END_TEST;
+}
+
+int UtcDaliHoverInterrupted(void)
+{
+ TestApplication application;
+
+ Actor actor = Actor::New();
+ actor.SetSize(100.0f, 100.0f);
+ actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+ Stage::GetCurrent().Add(actor);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Connect to actor's hovered signal
+ SignalData data;
+ HoverEventFunctor functor( data );
+ actor.HoveredSignal().Connect( &application, functor );
+
+ // Emit a started signal
+ application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, Vector2( 10.0f, 10.0f ) ) );
+ DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+ DALI_TEST_EQUALS( TouchPoint::Started, data.hoverEvent.points[0].state, TEST_LOCATION );
+ data.Reset();
+
+ // Emit an interrupted signal, we should be signalled regardless of whether there is a hit or not.
+ application.ProcessEvent( GenerateSingleHover( TouchPoint::Interrupted, Vector2( 200.0f, 200.0f /* Outside actor */ ) ) );
+ DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+ DALI_TEST_EQUALS( TouchPoint::Interrupted, data.hoverEvent.points[0].state, TEST_LOCATION );
+ data.Reset();
+
+ // Emit another interrupted signal, our signal handler should not be called.
+ application.ProcessEvent( GenerateSingleHover( TouchPoint::Interrupted, Vector2( 200.0f, 200.0f ) ) );
+ DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION );
+ END_TEST;
+}
+
+int UtcDaliHoverParentConsumer(void)
+{
+ TestApplication application;
+ Actor rootActor( Stage::GetCurrent().GetRootLayer() );
+
+ Actor actor = Actor::New();
+ actor.SetSize(100.0f, 100.0f);
+ actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+ Stage::GetCurrent().Add(actor);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Connect to actor's hovered signal
+ SignalData data;
+ HoverEventFunctor functor( data, false );
+ actor.HoveredSignal().Connect( &application, functor );
+
+ // Connect to root actor's hovered signal
+ SignalData rootData;
+ HoverEventFunctor rootFunctor( rootData ); // Consumes signal
+ rootActor.HoveredSignal().Connect( &application, rootFunctor );
+
+ Vector2 screenCoordinates( 10.0f, 10.0f );
+ Vector2 actorCoordinates, rootCoordinates;
+ actor.ScreenToLocal( actorCoordinates.x, actorCoordinates.y, screenCoordinates.x, screenCoordinates.y );
+ rootActor.ScreenToLocal( rootCoordinates.x, rootCoordinates.y, screenCoordinates.x, screenCoordinates.y );
+
+ // Emit a started signal
+ application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, screenCoordinates ) );
+ DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+ DALI_TEST_EQUALS( true, rootData.functorCalled, TEST_LOCATION );
+ DALI_TEST_EQUALS( 1u, data.hoverEvent.GetPointCount(), TEST_LOCATION );
+ DALI_TEST_EQUALS( 1u, rootData.hoverEvent.GetPointCount(), TEST_LOCATION );
+ DALI_TEST_EQUALS( TouchPoint::Started, data.hoverEvent.points[0].state, TEST_LOCATION );
+ DALI_TEST_EQUALS( TouchPoint::Started, rootData.hoverEvent.points[0].state, TEST_LOCATION );
+ DALI_TEST_EQUALS( screenCoordinates, data.hoverEvent.points[0].screen, TEST_LOCATION );
+ DALI_TEST_EQUALS( screenCoordinates, rootData.hoverEvent.points[0].screen, TEST_LOCATION );
+ DALI_TEST_EQUALS( actorCoordinates, data.hoverEvent.points[0].local, 0.1f, TEST_LOCATION );
+ DALI_TEST_EQUALS( rootCoordinates, rootData.hoverEvent.points[0].local, 0.1f, TEST_LOCATION );
+ DALI_TEST_CHECK( actor == data.hoverEvent.points[0].hitActor );
+ DALI_TEST_CHECK( actor == rootData.hoverEvent.points[0].hitActor );
+ data.Reset();
+ rootData.Reset();
+
+ // Emit a motion signal
+ screenCoordinates.x = screenCoordinates.y = 11.0f;
+ actor.ScreenToLocal( actorCoordinates.x, actorCoordinates.y, screenCoordinates.x, screenCoordinates.y );
+ rootActor.ScreenToLocal( rootCoordinates.x, rootCoordinates.y, screenCoordinates.x, screenCoordinates.y );
+ application.ProcessEvent( GenerateSingleHover( TouchPoint::Motion, screenCoordinates ) );
+ DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+ DALI_TEST_EQUALS( true, rootData.functorCalled, TEST_LOCATION );
+ DALI_TEST_EQUALS( 1u, data.hoverEvent.GetPointCount(), TEST_LOCATION );
+ DALI_TEST_EQUALS( 1u, rootData.hoverEvent.GetPointCount(), TEST_LOCATION );
+ DALI_TEST_EQUALS( TouchPoint::Motion, data.hoverEvent.points[0].state, TEST_LOCATION );
+ DALI_TEST_EQUALS( TouchPoint::Motion, rootData.hoverEvent.points[0].state, TEST_LOCATION );
+ DALI_TEST_EQUALS( screenCoordinates, data.hoverEvent.points[0].screen, TEST_LOCATION );
+ DALI_TEST_EQUALS( screenCoordinates, rootData.hoverEvent.points[0].screen, TEST_LOCATION );
+ DALI_TEST_EQUALS( actorCoordinates, data.hoverEvent.points[0].local, 0.1f, TEST_LOCATION );
+ DALI_TEST_EQUALS( rootCoordinates, rootData.hoverEvent.points[0].local, 0.1f, TEST_LOCATION );
+ DALI_TEST_CHECK( actor == data.hoverEvent.points[0].hitActor );
+ DALI_TEST_CHECK( actor == rootData.hoverEvent.points[0].hitActor );
+ data.Reset();
+ rootData.Reset();
+
+ // Emit a finished signal
+ screenCoordinates.x = screenCoordinates.y = 12.0f;
+ actor.ScreenToLocal( actorCoordinates.x, actorCoordinates.y, screenCoordinates.x, screenCoordinates.y );
+ rootActor.ScreenToLocal( rootCoordinates.x, rootCoordinates.y, screenCoordinates.x, screenCoordinates.y );
+ application.ProcessEvent( GenerateSingleHover( TouchPoint::Finished, screenCoordinates ) );
+ DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+ DALI_TEST_EQUALS( true, rootData.functorCalled, TEST_LOCATION );
+ DALI_TEST_EQUALS( 1u, data.hoverEvent.GetPointCount(), TEST_LOCATION );
+ DALI_TEST_EQUALS( 1u, rootData.hoverEvent.GetPointCount(), TEST_LOCATION );
+ DALI_TEST_EQUALS( TouchPoint::Finished, data.hoverEvent.points[0].state, TEST_LOCATION );
+ DALI_TEST_EQUALS( TouchPoint::Finished, rootData.hoverEvent.points[0].state, TEST_LOCATION );
+ DALI_TEST_EQUALS( screenCoordinates, data.hoverEvent.points[0].screen, TEST_LOCATION );
+ DALI_TEST_EQUALS( screenCoordinates, rootData.hoverEvent.points[0].screen, TEST_LOCATION );
+ DALI_TEST_EQUALS( actorCoordinates, data.hoverEvent.points[0].local, 0.1f, TEST_LOCATION );
+ DALI_TEST_EQUALS( rootCoordinates, rootData.hoverEvent.points[0].local, 0.1f, TEST_LOCATION );
+ DALI_TEST_CHECK( actor == data.hoverEvent.points[0].hitActor );
+ DALI_TEST_CHECK( actor == rootData.hoverEvent.points[0].hitActor );
+ data.Reset();
+ rootData.Reset();
+
+ // Emit a started signal where the actor is not present, will hit the root actor though
+ screenCoordinates.x = screenCoordinates.y = 200.0f;
+ rootActor.ScreenToLocal( rootCoordinates.x, rootCoordinates.y, screenCoordinates.x, screenCoordinates.y );
+ application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, screenCoordinates ) );
+ DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION );
+ DALI_TEST_EQUALS( true, rootData.functorCalled, TEST_LOCATION );
+ DALI_TEST_EQUALS( 1u, rootData.hoverEvent.GetPointCount(), TEST_LOCATION );
+ DALI_TEST_EQUALS( TouchPoint::Started, rootData.hoverEvent.points[0].state, TEST_LOCATION );
+ DALI_TEST_EQUALS( screenCoordinates, rootData.hoverEvent.points[0].screen, TEST_LOCATION );
+ DALI_TEST_EQUALS( rootCoordinates, rootData.hoverEvent.points[0].local, 0.1f, TEST_LOCATION );
+ DALI_TEST_CHECK( rootActor == rootData.hoverEvent.points[0].hitActor );
+ END_TEST;
+}
+
+int UtcDaliHoverInterruptedParentConsumer(void)
+{
+ TestApplication application;
+ Actor rootActor( Stage::GetCurrent().GetRootLayer() );
+
+ Actor actor = Actor::New();
+ actor.SetSize(100.0f, 100.0f);
+ actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+ Stage::GetCurrent().Add(actor);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Connect to actor's hovered signal
+ SignalData data;
+ HoverEventFunctor functor( data, false );
+ actor.HoveredSignal().Connect( &application, functor );
+
+ // Connect to root actor's hovered signal
+ SignalData rootData;
+ HoverEventFunctor rootFunctor( rootData ); // Consumes signal
+ rootActor.HoveredSignal().Connect( &application, rootFunctor );
+
+ // Emit a started signal
+ application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, Vector2( 10.0f, 10.0f ) ) );
+ DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+ DALI_TEST_EQUALS( true, rootData.functorCalled, TEST_LOCATION );
+ DALI_TEST_EQUALS( TouchPoint::Started, data.hoverEvent.points[0].state, TEST_LOCATION );
+ DALI_TEST_EQUALS( TouchPoint::Started, rootData.hoverEvent.points[0].state, TEST_LOCATION );
+ DALI_TEST_CHECK( actor == data.hoverEvent.points[0].hitActor );
+ DALI_TEST_CHECK( actor == rootData.hoverEvent.points[0].hitActor );
+ data.Reset();
+ rootData.Reset();
+
+ // Emit an interrupted signal
+ application.ProcessEvent( GenerateSingleHover( TouchPoint::Interrupted, Vector2( 200.0f, 200.0f ) ) );
+ DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+ DALI_TEST_EQUALS( true, rootData.functorCalled, TEST_LOCATION );
+ DALI_TEST_EQUALS( TouchPoint::Interrupted, data.hoverEvent.points[0].state, TEST_LOCATION );
+ DALI_TEST_EQUALS( TouchPoint::Interrupted, rootData.hoverEvent.points[0].state, TEST_LOCATION );
+ DALI_TEST_CHECK( actor == data.hoverEvent.points[0].hitActor );
+ DALI_TEST_CHECK( actor == rootData.hoverEvent.points[0].hitActor );
+ data.Reset();
+ rootData.Reset();
+
+ // Emit another started signal
+ application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, Vector2( 10.0f, 10.0f ) ) );
+ DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+ DALI_TEST_EQUALS( true, rootData.functorCalled, TEST_LOCATION );
+ DALI_TEST_EQUALS( TouchPoint::Started, data.hoverEvent.points[0].state, TEST_LOCATION );
+ DALI_TEST_EQUALS( TouchPoint::Started, rootData.hoverEvent.points[0].state, TEST_LOCATION );
+ data.Reset();
+ rootData.Reset();
+
+ // Remove actor from Stage
+ Stage::GetCurrent().Remove( actor );
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Emit an interrupted signal, only root actor's signal should be called.
+ application.ProcessEvent( GenerateSingleHover( TouchPoint::Interrupted, Vector2( 200.0f, 200.0f /* Outside actor */ ) ) );
+ DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION );
+ DALI_TEST_EQUALS( true, rootData.functorCalled, TEST_LOCATION );
+ DALI_TEST_EQUALS( TouchPoint::Interrupted, rootData.hoverEvent.points[0].state, TEST_LOCATION );
+ DALI_TEST_CHECK( rootActor == rootData.hoverEvent.points[0].hitActor );
+ data.Reset();
+ rootData.Reset();
+
+ // Emit another interrupted state, none of the signal's should be called.
+ application.ProcessEvent( GenerateSingleHover( TouchPoint::Interrupted, Vector2( 200.0f, 200.0f ) ) );
+ DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION );
+ DALI_TEST_EQUALS( false, rootData.functorCalled, TEST_LOCATION );
+ END_TEST;
+}
+
+int UtcDaliHoverLeave(void)
+{
+ TestApplication application;
+
+ Actor actor = Actor::New();
+ actor.SetSize(100.0f, 100.0f);
+ actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+ Stage::GetCurrent().Add(actor);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Connect to actor's hovered signal
+ SignalData data;
+ HoverEventFunctor functor( data );
+ actor.HoveredSignal().Connect( &application, functor );
+
+ // Set actor to require leave events
+ actor.SetLeaveRequired( true );
+
+ // Emit a started signal
+ application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, Vector2( 10.0f, 10.0f ) ) );
+ DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+ DALI_TEST_EQUALS( TouchPoint::Started, data.hoverEvent.points[0].state, TEST_LOCATION );
+ data.Reset();
+
+ // Emit a motion signal outside of actor, should be signalled with a Leave
+ application.ProcessEvent( GenerateSingleHover( TouchPoint::Motion, Vector2 ( 200.0f, 200.0f )) );
+ DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+ DALI_TEST_EQUALS( TouchPoint::Leave, data.hoverEvent.points[0].state, TEST_LOCATION );
+ data.Reset();
+
+ // Another motion outside of actor, no signalling
+ application.ProcessEvent( GenerateSingleHover( TouchPoint::Motion, Vector2 ( 201.0f, 201.0f )) );
+ DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION );
+ data.Reset();
+
+ // Another motion event inside actor, signalled with motion
+ application.ProcessEvent( GenerateSingleHover( TouchPoint::Motion, Vector2 ( 10.0f, 10.0f )) );
+ DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+ DALI_TEST_EQUALS( TouchPoint::Motion, data.hoverEvent.points[0].state, TEST_LOCATION );
+ data.Reset();
+
+ // We do not want to listen to leave events anymore
+ actor.SetLeaveRequired( false );
+
+ // Another motion event outside of actor, no signalling
+ application.ProcessEvent( GenerateSingleHover( TouchPoint::Motion, Vector2 ( 200.0f, 200.0f )) );
+ DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION );
+ data.Reset();
+ END_TEST;
+}
+
+int UtcDaliHoverLeaveParentConsumer(void)
+{
+ TestApplication application;
+ Actor rootActor( Stage::GetCurrent().GetRootLayer() );
+
+ Actor actor = Actor::New();
+ actor.SetSize(100.0f, 100.0f);
+ actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+ Stage::GetCurrent().Add(actor);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Connect to actor's hovered signal
+ SignalData data;
+ HoverEventFunctor functor( data, false );
+ actor.HoveredSignal().Connect( &application, functor );
+
+ // Connect to root actor's hovered signal
+ SignalData rootData;
+ HoverEventFunctor rootFunctor( rootData ); // Consumes signal
+ rootActor.HoveredSignal().Connect( &application, rootFunctor );
+
+ // Set actor to require leave events
+ actor.SetLeaveRequired( true );
+ rootActor.SetLeaveRequired( true );
+
+ // Emit a started signal
+ application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, Vector2( 10.0f, 10.0f ) ) );
+ DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+ DALI_TEST_EQUALS( true, rootData.functorCalled, TEST_LOCATION );
+ DALI_TEST_EQUALS( TouchPoint::Started, data.hoverEvent.points[0].state, TEST_LOCATION );
+ DALI_TEST_EQUALS( TouchPoint::Started, rootData.hoverEvent.points[0].state, TEST_LOCATION );
+ DALI_TEST_CHECK( actor == data.hoverEvent.points[0].hitActor );
+ DALI_TEST_CHECK( actor == rootData.hoverEvent.points[0].hitActor );
+ data.Reset();
+ rootData.Reset();
+
+ // Emit a motion signal outside of actor, should be signalled with a Leave
+ application.ProcessEvent( GenerateSingleHover( TouchPoint::Motion, Vector2 ( 200.0f, 200.0f )) );
+ DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+ DALI_TEST_EQUALS( true, rootData.functorCalled, TEST_LOCATION );
+ DALI_TEST_EQUALS( TouchPoint::Leave, data.hoverEvent.points[0].state, TEST_LOCATION );
+ DALI_TEST_EQUALS( TouchPoint::Leave, rootData.hoverEvent.points[0].state, TEST_LOCATION );
+ DALI_TEST_CHECK( actor == data.hoverEvent.points[0].hitActor );
+ DALI_TEST_CHECK( actor == rootData.hoverEvent.points[0].hitActor );
+ data.Reset();
+ rootData.Reset();
+
+ // Another motion outside of actor, only rootActor signalled
+ application.ProcessEvent( GenerateSingleHover( TouchPoint::Motion, Vector2 ( 201.0f, 201.0f )) );
+ DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION );
+ DALI_TEST_EQUALS( true, rootData.functorCalled, TEST_LOCATION );
+ DALI_TEST_EQUALS( TouchPoint::Motion, rootData.hoverEvent.points[0].state, TEST_LOCATION );
+ DALI_TEST_CHECK( rootActor == rootData.hoverEvent.points[0].hitActor );
+ data.Reset();
+ rootData.Reset();
+
+ // Another motion event inside actor, signalled with motion
+ application.ProcessEvent( GenerateSingleHover( TouchPoint::Motion, Vector2 ( 10.0f, 10.0f )) );
+ DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+ DALI_TEST_EQUALS( true, rootData.functorCalled, TEST_LOCATION );
+ DALI_TEST_EQUALS( TouchPoint::Motion, data.hoverEvent.points[0].state, TEST_LOCATION );
+ DALI_TEST_EQUALS( TouchPoint::Motion, rootData.hoverEvent.points[0].state, TEST_LOCATION );
+ DALI_TEST_CHECK( actor == data.hoverEvent.points[0].hitActor );
+ DALI_TEST_CHECK( actor == rootData.hoverEvent.points[0].hitActor );
+ data.Reset();
+ rootData.Reset();
+
+ // We do not want to listen to leave events of actor anymore
+ actor.SetLeaveRequired( false );
+
+ // Another motion event outside of root actor, only root signalled
+ Vector2 stageSize( Stage::GetCurrent().GetSize() );
+ application.ProcessEvent( GenerateSingleHover( TouchPoint::Motion, Vector2 ( stageSize.width + 10.0f, stageSize.height + 10.0f )) );
+ DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION );
+ DALI_TEST_EQUALS( true, rootData.functorCalled, TEST_LOCATION );
+ DALI_TEST_EQUALS( TouchPoint::Leave, rootData.hoverEvent.points[0].state, TEST_LOCATION );
+ END_TEST;
+}
+
+int UtcDaliHoverActorBecomesInsensitive(void)
+{
+ TestApplication application;
+
+ Actor actor = Actor::New();
+ actor.SetSize(100.0f, 100.0f);
+ actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+ Stage::GetCurrent().Add(actor);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Connect to actor's hovered signal
+ SignalData data;
+ HoverEventFunctor functor( data );
+ actor.HoveredSignal().Connect( &application, functor );
+
+ // Emit a started signal
+ application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, Vector2( 10.0f, 10.0f ) ) );
+ DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+ DALI_TEST_EQUALS( TouchPoint::Started, data.hoverEvent.points[0].state, TEST_LOCATION );
+ data.Reset();
+
+ // Change actor to insensitive
+ actor.SetSensitive( false );
+
+ // Emit a motion signal, signalled with an interrupted
+ application.ProcessEvent( GenerateSingleHover( TouchPoint::Motion, Vector2 ( 200.0f, 200.0f )) );
+ DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+ DALI_TEST_EQUALS( TouchPoint::Interrupted, data.hoverEvent.points[0].state, TEST_LOCATION );
+ data.Reset();
+ END_TEST;
+}
+
+int UtcDaliHoverActorBecomesInsensitiveParentConsumer(void)
+{
+ TestApplication application;
+ Actor rootActor( Stage::GetCurrent().GetRootLayer() );
+
+ Actor actor = Actor::New();
+ actor.SetSize(100.0f, 100.0f);
+ actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+ Stage::GetCurrent().Add(actor);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Connect to actor's hovered signal
+ SignalData data;
+ HoverEventFunctor functor( data, false );
+ actor.HoveredSignal().Connect( &application, functor );
+
+ // Connect to root actor's hovered signal
+ SignalData rootData;
+ HoverEventFunctor rootFunctor( rootData ); // Consumes signal
+ rootActor.HoveredSignal().Connect( &application, rootFunctor );
+
+ // Emit a started signal
+ application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, Vector2( 10.0f, 10.0f ) ) );
+ DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+ DALI_TEST_EQUALS( true, rootData.functorCalled, TEST_LOCATION );
+ DALI_TEST_EQUALS( TouchPoint::Started, data.hoverEvent.points[0].state, TEST_LOCATION );
+ DALI_TEST_EQUALS( TouchPoint::Started, rootData.hoverEvent.points[0].state, TEST_LOCATION );
+ DALI_TEST_CHECK( actor == data.hoverEvent.points[0].hitActor );
+ DALI_TEST_CHECK( actor == rootData.hoverEvent.points[0].hitActor );
+ data.Reset();
+ rootData.Reset();
+
+ // Remove actor from Stage
+ Stage::GetCurrent().Remove( actor );
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Make root actor insensitive
+ rootActor.SetSensitive( false );
+
+ // Emit a motion signal, signalled with an interrupted (should get interrupted even if within root actor)
+ application.ProcessEvent( GenerateSingleHover( TouchPoint::Motion, Vector2 ( 200.0f, 200.0f )) );
+ DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION );
+ DALI_TEST_EQUALS( true, rootData.functorCalled, TEST_LOCATION );
+ DALI_TEST_EQUALS( TouchPoint::Interrupted, rootData.hoverEvent.points[0].state, TEST_LOCATION );
+ END_TEST;
+}
+
+int UtcDaliHoverMultipleLayers(void)
+{
+ TestApplication application;
+ Actor rootActor( Stage::GetCurrent().GetRootLayer() );
+
+ // Connect to actor's hovered signal
+ SignalData data;
+ HoverEventFunctor functor( data );
+
+ Layer layer1 ( Layer::New() );
+ layer1.SetSize(100.0f, 100.0f);
+ layer1.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+ Stage::GetCurrent().Add( layer1 );
+
+ Actor actor1 ( Actor::New() );
+ actor1.SetSize( 100.0f, 100.0f );
+ actor1.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+ actor1.SetZ( 1.0f ); // Should hit actor1 in this layer
+ layer1.Add( actor1 );
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Connect to layer1 and actor1
+ layer1.HoveredSignal().Connect( &application, functor );
+ actor1.HoveredSignal().Connect( &application, functor );
+
+ // Hit in hittable area, actor1 should be hit
+ application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, Vector2( 10.0f, 10.0f ) ) );
+ DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+ DALI_TEST_CHECK( data.hoveredActor == actor1 );
+ data.Reset();
+
+ // Make layer1 insensitive, nothing should be hit
+ layer1.SetSensitive( false );
+ application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, Vector2( 10.0f, 10.0f ) ) );
+ DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION );
+ data.Reset();
+
+ // Make layer1 sensitive again, again actor1 will be hit
+ layer1.SetSensitive( true );
+ application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, Vector2( 10.0f, 10.0f ) ) );
+ DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+ DALI_TEST_CHECK( data.hoveredActor == actor1 );
+ data.Reset();
+
+ // Make rootActor insensitive, nothing should be hit
+ rootActor.SetSensitive( false );
+ application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, Vector2( 10.0f, 10.0f ) ) );
+ DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION );
+ data.Reset();
+
+ // Make rootActor sensitive
+ rootActor.SetSensitive( true );
+
+ // Add another layer
+ Layer layer2 ( Layer::New() );
+ layer2.SetSize(100.0f, 100.0f );
+ layer2.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+ layer2.SetZ( 10.0f ); // Should hit layer2 in this layer rather than actor2
+ Stage::GetCurrent().Add( layer2 );
+
+ Actor actor2 ( Actor::New() );
+ actor2.SetSize(100.0f, 100.0f);
+ actor2.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+ layer2.Add( actor2 );
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Connect to layer2 and actor2
+ layer2.HoveredSignal().Connect( &application, functor );
+ actor2.HoveredSignal().Connect( &application, functor );
+
+ // Emit an event, should hit layer2
+ application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, Vector2( 10.0f, 10.0f ) ) );
+ DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+ //DALI_TEST_CHECK( data.hoveredActor == layer2 ); // TODO: Uncomment this after removing renderable hack!
+ data.Reset();
+
+ // Make layer2 insensitive, should hit actor1
+ layer2.SetSensitive( false );
+ application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, Vector2( 10.0f, 10.0f ) ) );
+ DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+ DALI_TEST_CHECK( data.hoveredActor == actor1 );
+ data.Reset();
+
+ // Make layer2 sensitive again, should hit layer2
+ layer2.SetSensitive( true );
+ application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, Vector2( 10.0f, 10.0f ) ) );
+ DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+ //DALI_TEST_CHECK( data.hoveredActor == layer2 ); // TODO: Uncomment this after removing renderable hack!
+ data.Reset();
+
+ // Make layer2 invisible, render and notify
+ layer2.SetVisible( false );
+ application.SendNotification();
+ application.Render();
+
+ // Should hit actor1
+ application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, Vector2( 10.0f, 10.0f ) ) );
+ DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+ DALI_TEST_CHECK( data.hoveredActor == actor1 );
+ data.Reset();
+
+ // Make rootActor invisible, render and notify
+ rootActor.SetVisible( false );
+ application.SendNotification();
+ application.Render();
+
+ // Should not hit anything
+ application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, Vector2( 10.0f, 10.0f ) ) );
+ DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION );
+ data.Reset();
+ END_TEST;
+}
+
+int UtcDaliHoverMultipleRenderTasks(void)
+{
+ TestApplication application;
+ Stage stage ( Stage::GetCurrent() );
+ Vector2 stageSize ( stage.GetSize() );
+
+ Actor actor = Actor::New();
+ actor.SetSize(100.0f, 100.0f);
+ actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+ stage.Add(actor);
+
+ // Create render task
+ Viewport viewport( stageSize.width * 0.5f, stageSize.height * 0.5f, stageSize.width * 0.5f, stageSize.height * 0.5f );
+ RenderTask renderTask ( Stage::GetCurrent().GetRenderTaskList().CreateTask() );
+ renderTask.SetViewport( viewport );
+ renderTask.SetInputEnabled( true );
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Connect to actor's hovered signal
+ SignalData data;
+ HoverEventFunctor functor( data );
+ actor.HoveredSignal().Connect( &application, functor );
+
+ // Emit a started signal
+ application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, Vector2( 10.0f, 10.0f ) ) );
+ DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+ data.Reset();
+
+ // Ensure renderTask actor can be hit too.
+ application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, Vector2( viewport.x + 5.0f, viewport.y + 5.0f ) ) );
+ DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+ data.Reset();
+
+ // Disable input on renderTask, should not be hittable
+ renderTask.SetInputEnabled( false );
+ application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, Vector2( viewport.x + 5.0f, viewport.y + 5.0f ) ) );
+ DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION );
+ data.Reset();
+ END_TEST;
+}
+
+int UtcDaliHoverMultipleRenderTasksWithChildLayer(void)
+{
+ TestApplication application;
+ Stage stage ( Stage::GetCurrent() );
+ Vector2 stageSize ( stage.GetSize() );
+
+ Actor actor = Actor::New();
+ actor.SetSize(100.0f, 100.0f);
+ actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+ stage.Add(actor);
+
+ Layer layer = Layer::New();
+ layer.SetSize(100.0f, 100.0f);
+ layer.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+ actor.Add(layer);
+
+ // Create render task
+ Viewport viewport( stageSize.width * 0.5f, stageSize.height * 0.5f, stageSize.width * 0.5f, stageSize.height * 0.5f );
+ RenderTask renderTask ( Stage::GetCurrent().GetRenderTaskList().CreateTask() );
+ renderTask.SetViewport( viewport );
+ renderTask.SetInputEnabled( true );
+ renderTask.SetSourceActor( actor );
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Connect to layer's hovered signal
+ SignalData data;
+ HoverEventFunctor functor( data );
+ actor.HoveredSignal().Connect( &application, functor );
+ layer.HoveredSignal().Connect( &application, functor );
+
+ // Emit a started signal
+ application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, Vector2( 10.0f, 10.0f ) ) );
+ DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+ data.Reset();
+
+ // Ensure renderTask actor can be hit too.
+ application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, Vector2( viewport.x + 5.0f, viewport.y + 5.0f ) ) );
+ DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+ data.Reset();
+
+ // Disable input on renderTask, should not be hittable
+ renderTask.SetInputEnabled( false );
+ application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, Vector2( viewport.x + 5.0f, viewport.y + 5.0f ) ) );
+ DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION );
+ data.Reset();
+ END_TEST;
+}
+
+int UtcDaliHoverOffscreenRenderTasks(void)
+{
+ TestApplication application;
+ Stage stage ( Stage::GetCurrent() );
+ Vector2 stageSize ( stage.GetSize() );
+
+ // FrameBufferImage for offscreen RenderTask
+ FrameBufferImage frameBufferImage( FrameBufferImage::New( stageSize.width, stageSize.height, Pixel::RGBA8888 ) );
+
+ // Create an image actor to display the FrameBufferImage
+ ImageActor imageActor ( ImageActor::New( frameBufferImage ) );
+ imageActor.SetParentOrigin(ParentOrigin::CENTER);
+ imageActor.SetSize( stageSize.x, stageSize.y );
+ imageActor.ScaleBy( Vector3(1.0f, -1.0f, 1.0f) ); // FIXME
+ stage.Add( imageActor );
+
+ Actor actor = Actor::New();
+ actor.SetSize(100.0f, 100.0f);
+ actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+ stage.Add( actor );
+ application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE ); // Ensure framebuffer connects
+
+ stage.GetRenderTaskList().GetTask( 0u ).SetScreenToFrameBufferFunction( RenderTask::FULLSCREEN_FRAMEBUFFER_FUNCTION );
+
+ // Create a RenderTask
+ RenderTask renderTask = stage.GetRenderTaskList().CreateTask();
+ renderTask.SetSourceActor( actor );
+ renderTask.SetTargetFrameBuffer( frameBufferImage );
+ renderTask.SetInputEnabled( true );
+
+ // Create another RenderTask
+ RenderTask renderTask2( stage.GetRenderTaskList().CreateTask() );
+ renderTask2.SetInputEnabled( true );
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Connect to actor's hovered signal
+ SignalData data;
+ HoverEventFunctor functor( data );
+ actor.HoveredSignal().Connect( &application, functor );
+
+ // Emit a started signal
+ application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, Vector2( 10.0f, 10.0f ) ) );
+ DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+ data.Reset();
+ END_TEST;
+}
+
+int UtcDaliHoverMultipleRenderableActors(void)
+{
+ TestApplication application;
+ Stage stage ( Stage::GetCurrent() );
+ Vector2 stageSize ( stage.GetSize() );
+
+ Actor parent = ImageActor::New();
+ parent.SetSize(100.0f, 100.0f);
+ parent.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+ stage.Add(parent);
+
+ Actor actor = ImageActor::New();
+ actor.SetSize(100.0f, 100.0f);
+ actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+ parent.Add(actor);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Connect to layer's hovered signal
+ SignalData data;
+ HoverEventFunctor functor( data );
+ parent.HoveredSignal().Connect( &application, functor );
+ actor.HoveredSignal().Connect( &application, functor );
+
+ // Emit a started signal
+ application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, Vector2( 10.0f, 10.0f ) ) );
+ DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+ DALI_TEST_CHECK( actor == data.hoveredActor );
+ END_TEST;
+}
+
+int UtcDaliHoverActorRemovedInSignal(void)
+{
+ TestApplication application;
+
+ Actor actor = Actor::New();
+ actor.SetSize(100.0f, 100.0f);
+ actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+ Stage::GetCurrent().Add(actor);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Connect to actor's hovered signal
+ SignalData data;
+ RemoveActorFunctor functor( data );
+ actor.HoveredSignal().Connect( &application, functor );
+
+ // Register for leave events
+ actor.SetLeaveRequired( true );
+
+ // Emit a started signal
+ application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, Vector2( 10.0f, 10.0f ) ) );
+ DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+ data.Reset();
+
+ // Re-add, render and notify
+ Stage::GetCurrent().Add(actor);
+ application.SendNotification();
+ application.Render();
+
+ // Emit another signal outside of actor's area, should not get anything as the scene has changed.
+ application.ProcessEvent( GenerateSingleHover( TouchPoint::Motion, Vector2( 210.0f, 210.0f ) ) );
+ DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION );
+ data.Reset();
+
+ // Emit a started signal
+ application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, Vector2( 10.0f, 10.0f ) ) );
+ DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+ data.Reset();
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Emit another signal outside of actor's area, should not get anything as the scene has changed.
+ application.ProcessEvent( GenerateSingleHover( TouchPoint::Motion, Vector2( 210.0f, 210.0f ) ) );
+ DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION );
+ data.Reset();
+
+ // Re-add actor back to stage, render and notify
+ Stage::GetCurrent().Add(actor);
+ application.SendNotification();
+ application.Render();
+
+ // Emit another started event
+ application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, Vector2( 10.0f, 10.0f ) ) );
+ DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+ data.Reset();
+
+ // Completely delete the actor
+ actor = NULL;
+
+ // Emit event, should not crash and should not receive an event.
+ application.ProcessEvent( GenerateSingleHover( TouchPoint::Motion, Vector2( 210.0f, 210.0f ) ) );
+ DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION );
+ END_TEST;
+}
+
+int UtcDaliHoverActorSignalNotConsumed(void)
+{
+ TestApplication application;
+
+ Actor actor = Actor::New();
+ actor.SetSize(100.0f, 100.0f);
+ actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+ Stage::GetCurrent().Add(actor);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Connect to actor's hovered signal
+ SignalData data;
+ HoverEventFunctor functor( data, false );
+ actor.HoveredSignal().Connect( &application, functor );
+
+ // Emit a started signal
+ application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, Vector2( 10.0f, 10.0f ) ) );
+ DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+ END_TEST;
+}
+
+int UtcDaliHoverActorUnStaged(void)
+{
+ TestApplication application;
+
+ Actor actor = Actor::New();
+ actor.SetSize(100.0f, 100.0f);
+ actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+ Stage::GetCurrent().Add(actor);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Connect to actor's hovered signal
+ SignalData data;
+ HoverEventFunctor functor( data );
+ actor.HoveredSignal().Connect( &application, functor );
+
+ // Emit a started signal
+ application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, Vector2( 10.0f, 10.0f ) ) );
+ DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+ data.Reset();
+
+ // Remove actor from stage
+ Stage::GetCurrent().Remove( actor );
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Emit a move at the same point, we should not be signalled.
+ application.ProcessEvent( GenerateSingleHover( TouchPoint::Motion, Vector2( 10.0f, 10.0f ) ) );
+ DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION );
+ data.Reset();
+ END_TEST;
+}
+
+int UtcDaliHoverSystemOverlayActor(void)
+{
+ TestApplication application;
+ Dali::Integration::Core& core( application.GetCore() );
+ Dali::Integration::SystemOverlay& systemOverlay( core.GetSystemOverlay() );
+ systemOverlay.GetOverlayRenderTasks().CreateTask();
+
+ // Create an actor and add it to the system overlay.
+ Actor systemActor = Actor::New();
+ systemActor.SetSize(100.0f, 100.0f);
+ systemActor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+ systemOverlay.Add( systemActor );
+
+ // Create an actor and add it to the stage as per normal, same position and size as systemActor
+ Actor actor = Actor::New();
+ actor.SetSize(100.0f, 100.0f);
+ actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+ Stage::GetCurrent().Add(actor);
+
+ // Connect to the hover signals.
+ SignalData data;
+ HoverEventFunctor functor( data );
+ systemActor.HoveredSignal().Connect( &application, functor );
+ actor.HoveredSignal().Connect( &application, functor );
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Emit a started signal, the system overlay is drawn last so is at the top, should hit the systemActor.
+ application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, Vector2( 10.0f, 10.0f ) ) );
+ DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+ DALI_TEST_CHECK( systemActor == data.hoveredActor );
+ END_TEST;
+}
+
+int UtcDaliHoverLeaveActorReadded(void)
+{
+ TestApplication application;
+ Stage stage = Stage::GetCurrent();
+
+ Actor actor = Actor::New();
+ actor.SetSize(100.0f, 100.0f);
+ actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+ stage.Add(actor);
+
+ // Set actor to receive hover-events
+ actor.SetLeaveRequired( true );
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Connect to actor's hovered signal
+ SignalData data;
+ HoverEventFunctor functor( data );
+ actor.HoveredSignal().Connect( &application, functor );
+
+ // Emit a started and motion
+ application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, Vector2( 10.0f, 10.0f ) ) );
+ application.ProcessEvent( GenerateSingleHover( TouchPoint::Motion, Vector2( 11.0f, 10.0f ) ) );
+ DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+ data.Reset();
+
+ // Remove actor from stage and add again
+ stage.Remove( actor );
+ stage.Add( actor );
+
+ // Emit a motion within the actor's bounds
+ application.ProcessEvent( GenerateSingleHover( TouchPoint::Motion, Vector2( 12.0f, 10.0f ) ) );
+ DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+ data.Reset();
+
+ // Emit a motion outside the actor's bounds
+ application.ProcessEvent( GenerateSingleHover( TouchPoint::Motion, Vector2( 200.0f, 200.0f ) ) );
+ DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+ DALI_TEST_EQUALS( TouchPoint::Leave, data.hoverEvent.points[0].state, TEST_LOCATION );
+ data.Reset();
+
+ END_TEST;
+}
+
+int UtcDaliHoverStencil(void)
+{
+ TestApplication application;
+ Stage stage = Stage::GetCurrent();
+
+ TextActor actor = TextActor::New();
+ actor.SetSize(100.0f, 100.0f);
+ actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+ stage.Add(actor);
+
+ Actor stencil = Actor::New();
+ stencil.SetSize(50.0f, 50.0f);
+ stencil.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+ stencil.SetDrawMode( DrawMode::STENCIL );
+ stage.Add(stencil);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Connect to actor's hovered signal
+ SignalData data;
+ HoverEventFunctor functor( data );
+ actor.HoveredSignal().Connect( &application, functor );
+
+ // Emit an event within stencil area
+ application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, Vector2( 10.0f, 10.0f ) ) );
+ DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+ data.Reset();
+
+ // Emit an event outside the stencil area but within the actor area
+ application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, Vector2( 60.0f, 60.0f ) ) );
+ DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION );
+ data.Reset();
+
+ END_TEST;
+}
+
+int UtcDaliHoverStencilInActorHierarchy(void)
+{
+ TestApplication application;
+ Stage stage = Stage::GetCurrent();
+
+ TextActor parent = TextActor::New();
+ parent.SetSize(100.0f, 100.0f);
+ parent.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+ stage.Add(parent);
+
+ TextActor child = TextActor::New();
+ child.SetSize(25.0f, 25.0f);
+ child.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+ parent.Add(child);
+
+ Actor stencil = Actor::New();
+ stencil.SetSize(50.0f, 50.0f);
+ stencil.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+ stencil.SetDrawMode( DrawMode::STENCIL );
+ stage.Add(stencil);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Connect to hover signals
+ SignalData parentData;
+ parent.HoveredSignal().Connect( &application, HoverEventFunctor(parentData) );
+ SignalData childData;
+ child.HoveredSignal().Connect( &application, HoverEventFunctor(childData) );
+
+ // Emit an event within stencil area
+ application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, Vector2( 10.0f, 10.0f ) ) );
+ DALI_TEST_EQUALS( false, parentData.functorCalled, TEST_LOCATION );
+ DALI_TEST_EQUALS( true, childData.functorCalled, TEST_LOCATION );
+ parentData.Reset();
+ childData.Reset();
+
+ // Emit an event outside child area and within stencil area
+ application.ProcessEvent( GenerateSingleHover( TouchPoint::Motion, Vector2( 40.0f, 40.0f ) ) );
+ DALI_TEST_EQUALS( true, parentData.functorCalled, TEST_LOCATION );
+ DALI_TEST_EQUALS( false, childData.functorCalled, TEST_LOCATION );
+ parentData.Reset();
+ childData.Reset();
+
+ // Emit an event outside stencil are but within parent area
+ application.ProcessEvent( GenerateSingleHover( TouchPoint::Motion, Vector2( 60.0f, 60.0f ) ) );
+ DALI_TEST_EQUALS( false, parentData.functorCalled, TEST_LOCATION );
+ DALI_TEST_EQUALS( false, childData.functorCalled, TEST_LOCATION );
+ parentData.Reset();
+ childData.Reset();
+
+ // Readd actor (so that stencil is the first child)
+ stage.Remove(parent);
+ application.SendNotification();
+ application.Render();
+ stage.Add(parent);
+ application.SendNotification();
+ application.Render();
+
+ // Redo hit in same area...
+
+ // Emit an event within stencil area
+ application.ProcessEvent( GenerateSingleHover( TouchPoint::Motion, Vector2( 10.0f, 10.0f ) ) );
+ DALI_TEST_EQUALS( false, parentData.functorCalled, TEST_LOCATION );
+ DALI_TEST_EQUALS( true, childData.functorCalled, TEST_LOCATION );
+ parentData.Reset();
+ childData.Reset();
+
+ // Emit an event outside child area and within stencil area
+ application.ProcessEvent( GenerateSingleHover( TouchPoint::Motion, Vector2( 40.0f, 40.0f ) ) );
+ DALI_TEST_EQUALS( true, parentData.functorCalled, TEST_LOCATION );
+ DALI_TEST_EQUALS( false, childData.functorCalled, TEST_LOCATION );
+ parentData.Reset();
+ childData.Reset();
+
+ // Emit an event outside stencil are but within parent area
+ application.ProcessEvent( GenerateSingleHover( TouchPoint::Motion, Vector2( 60.0f, 60.0f ) ) );
+ DALI_TEST_EQUALS( false, parentData.functorCalled, TEST_LOCATION );
+ DALI_TEST_EQUALS( false, childData.functorCalled, TEST_LOCATION );
+ parentData.Reset();
+ childData.Reset();
+
+ END_TEST;
+}
+
+int UtcDaliHoverMultipleStencils(void)
+{
+ TestApplication application;
+ Stage stage = Stage::GetCurrent();
+
+ TextActor actor = TextActor::New();
+ actor.SetSize(100.0f, 100.0f);
+ actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+ stage.Add(actor);
+
+ Actor stencil = Actor::New();
+ stencil.SetSize(50.0f, 50.0f);
+ stencil.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+ stencil.SetDrawMode( DrawMode::STENCIL );
+ stage.Add(stencil);
+
+ Actor stencil2 = Actor::New();
+ stencil2.SetSize(50.0f, 50.0f);
+ stencil2.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+ stencil2.SetDrawMode( DrawMode::STENCIL );
+ stencil2.SetPosition(50.0f, 50.0f);
+ stage.Add(stencil2);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Connect to actor's hovered signal
+ SignalData data;
+ HoverEventFunctor functor( data );
+ actor.HoveredSignal().Connect( &application, functor );
+
+ // Emit an event within stencil area
+ application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, Vector2( 10.0f, 10.0f ) ) );
+ DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+ data.Reset();
+
+ // Emit an event inside the second stencil area
+ application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, Vector2( 60.0f, 60.0f ) ) );
+ DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+ data.Reset();
+
+ // Emit an event outside both stencil areas but within the actor area
+ application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, Vector2( 10.0f, 60.0f ) ) );
+ DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION );
+ data.Reset();
+
+ END_TEST;
+}
+
+int UtcDaliHoverStencilNonRenderableActor(void)
+{
+ TestApplication application;
+ Stage stage = Stage::GetCurrent();
+
+ Actor actor = Actor::New();
+ actor.SetSize(100.0f, 100.0f);
+ actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+ stage.Add(actor);
+
+ Actor stencil = Actor::New();
+ stencil.SetSize(50.0f, 50.0f);
+ stencil.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+ stencil.SetDrawMode( DrawMode::STENCIL );
+ stage.Add(stencil);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Connect to actor's hovered signal
+ SignalData data;
+ HoverEventFunctor functor( data );
+ actor.HoveredSignal().Connect( &application, functor );
+
+ // Emit an event within stencil area
+ application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, Vector2( 10.0f, 10.0f ) ) );
+ DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+ data.Reset();
+
+ // Emit an event outside the stencil area but within the actor area, we should have a hit!
+ application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, Vector2( 60.0f, 60.0f ) ) );
+ DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+ data.Reset();
+
+ END_TEST;
+}
END_TEST;
}
+int UtcDaliLayerHoverConsumed(void)
+{
+ TestApplication application;
+ Layer layer = Layer::New();
+
+ DALI_TEST_EQUALS( layer.IsHoverConsumed(), false, TEST_LOCATION );
+ layer.SetHoverConsumed( true );
+ DALI_TEST_EQUALS( layer.IsHoverConsumed(), true, TEST_LOCATION );
+ END_TEST;
+}
+
int UtcDaliLayerClippingGLCalls(void)
{
TestApplication application;
DALI_TEST_EQUALS( testBox.y, stage.GetSize().height - glScissorParams.y - testBox.height, TEST_LOCATION ); // GL Coordinates are from bottom left
DALI_TEST_EQUALS( testBox.width, glScissorParams.width, TEST_LOCATION );
DALI_TEST_EQUALS( testBox.height, glScissorParams.height, TEST_LOCATION );
-
END_TEST;
}
#include <dali/public-api/dali-core.h>
#include <dali/integration-api/events/touch-event-combiner.h>
#include <dali/integration-api/events/touch-event-integ.h>
+#include <dali/integration-api/events/hover-event-integ.h>
#include <dali-test-suite-utils.h>
using namespace Dali;
// Down event
{
Integration::TouchEvent touchEvent;
+ Integration::HoverEvent hoverEvent;
TouchPoint point( 1, TouchPoint::Down, 100.0f, 100.0f );
- DALI_TEST_EQUALS( true, combiner.GetNextTouchEvent( point, time, touchEvent ), TEST_LOCATION );
+ DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchTouch, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION );
DALI_TEST_EQUALS( touchEvent.GetPointCount(), 1u, TEST_LOCATION );
DALI_TEST_EQUALS( touchEvent.points[0].deviceId, point.deviceId, TEST_LOCATION );
DALI_TEST_EQUALS( touchEvent.points[0].state, point.state, TEST_LOCATION );
// Motion in X direction
{
Integration::TouchEvent touchEvent;
+ Integration::HoverEvent hoverEvent;
TouchPoint point( 1, TouchPoint::Motion, 101.0f, 100.0f );
- DALI_TEST_EQUALS( true, combiner.GetNextTouchEvent( point, time, touchEvent ), TEST_LOCATION );
+ DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchTouch, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION );
DALI_TEST_EQUALS( touchEvent.GetPointCount(), 1u, TEST_LOCATION );
DALI_TEST_EQUALS( touchEvent.points[0].deviceId, point.deviceId, TEST_LOCATION );
DALI_TEST_EQUALS( touchEvent.points[0].state, point.state, TEST_LOCATION );
// Motion in Y direction
{
Integration::TouchEvent touchEvent;
+ Integration::HoverEvent hoverEvent;
TouchPoint point( 1, TouchPoint::Motion, 101.0f, 101.0f );
- DALI_TEST_EQUALS( true, combiner.GetNextTouchEvent( point, time, touchEvent ), TEST_LOCATION );
+ DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchTouch, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION );
DALI_TEST_EQUALS( touchEvent.GetPointCount(), 1u, TEST_LOCATION );
DALI_TEST_EQUALS( touchEvent.points[0].deviceId, point.deviceId, TEST_LOCATION );
DALI_TEST_EQUALS( touchEvent.points[0].state, point.state, TEST_LOCATION );
// Motion event, but same time
{
Integration::TouchEvent touchEvent;
+ Integration::HoverEvent hoverEvent;
TouchPoint point( 1, TouchPoint::Motion, 102.0f, 102.0f );
- DALI_TEST_EQUALS( false, combiner.GetNextTouchEvent( point, time, touchEvent ), TEST_LOCATION );
+ DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchNone, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION );
}
time++;
// Motion event, both X and Y movement
{
Integration::TouchEvent touchEvent;
+ Integration::HoverEvent hoverEvent;
TouchPoint point( 1, TouchPoint::Motion, 102.0f, 102.0f );
- DALI_TEST_EQUALS( true, combiner.GetNextTouchEvent( point, time, touchEvent ), TEST_LOCATION );
+ DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchTouch, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION );
DALI_TEST_EQUALS( touchEvent.GetPointCount(), 1u, TEST_LOCATION );
DALI_TEST_EQUALS( touchEvent.points[0].deviceId, point.deviceId, TEST_LOCATION );
DALI_TEST_EQUALS( touchEvent.points[0].state, point.state, TEST_LOCATION );
// Motion event, no movement
{
Integration::TouchEvent touchEvent;
+ Integration::HoverEvent hoverEvent;
TouchPoint point( 1, TouchPoint::Motion, 102.0f, 102.0f );
- DALI_TEST_EQUALS( false, combiner.GetNextTouchEvent( point, time, touchEvent ), TEST_LOCATION );
+ DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchNone, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION );
}
// Up event, no time diff, no movement
{
Integration::TouchEvent touchEvent;
+ Integration::HoverEvent hoverEvent;
TouchPoint point( 1, TouchPoint::Up, 102.0f, 102.0f );
- DALI_TEST_EQUALS( true, combiner.GetNextTouchEvent( point, time, touchEvent ), TEST_LOCATION );
+ DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchTouch, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION );
DALI_TEST_EQUALS( touchEvent.GetPointCount(), 1u, TEST_LOCATION );
DALI_TEST_EQUALS( touchEvent.points[0].deviceId, point.deviceId, TEST_LOCATION );
DALI_TEST_EQUALS( touchEvent.points[0].state, point.state, TEST_LOCATION );
// Motion event
{
Integration::TouchEvent touchEvent;
+ Integration::HoverEvent hoverEvent;
TouchPoint point( 1, TouchPoint::Motion, 100.0f, 100.0f );
- DALI_TEST_EQUALS( false, combiner.GetNextTouchEvent( point, time, touchEvent ), TEST_LOCATION );
+ DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchHover, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION );
+ DALI_TEST_EQUALS( hoverEvent.GetPointCount(), 1u, TEST_LOCATION );
+ DALI_TEST_EQUALS( hoverEvent.points[0].deviceId, point.deviceId, TEST_LOCATION );
+ DALI_TEST_EQUALS( hoverEvent.points[0].state, TouchPoint::Started, TEST_LOCATION );
+ DALI_TEST_EQUALS( hoverEvent.points[0].screen, point.screen, TEST_LOCATION );
}
time++;
// Motion event
{
Integration::TouchEvent touchEvent;
+ Integration::HoverEvent hoverEvent;
TouchPoint point( 1, TouchPoint::Motion, 102.0f, 102.0f );
- DALI_TEST_EQUALS( false, combiner.GetNextTouchEvent( point, time, touchEvent ), TEST_LOCATION );
+ DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchHover, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION );
+ DALI_TEST_EQUALS( hoverEvent.GetPointCount(), 1u, TEST_LOCATION );
+ DALI_TEST_EQUALS( hoverEvent.points[0].deviceId, point.deviceId, TEST_LOCATION );
+ DALI_TEST_EQUALS( hoverEvent.points[0].state, point.state, TEST_LOCATION );
+ DALI_TEST_EQUALS( hoverEvent.points[0].screen, point.screen, TEST_LOCATION );
+ }
+ END_TEST;
+}
+
+int UtcDaliTouchEventCombinerSingleTouchMotionFollowedByDown(void)
+{
+ TouchEventCombiner combiner;
+ unsigned long time( 0u );
+
+ // Motion event
+ {
+ Integration::TouchEvent touchEvent;
+ Integration::HoverEvent hoverEvent;
+ TouchPoint point( 1, TouchPoint::Motion, 100.0f, 100.0f );
+
+ DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchHover, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION );
+ DALI_TEST_EQUALS( hoverEvent.GetPointCount(), 1u, TEST_LOCATION );
+ DALI_TEST_EQUALS( hoverEvent.points[0].deviceId, point.deviceId, TEST_LOCATION );
+ DALI_TEST_EQUALS( hoverEvent.points[0].state, TouchPoint::Started, TEST_LOCATION );
+ DALI_TEST_EQUALS( hoverEvent.points[0].screen, point.screen, TEST_LOCATION );
+ }
+
+ time++;
+
+ // Motion event
+ {
+ Integration::TouchEvent touchEvent;
+ Integration::HoverEvent hoverEvent;
+ TouchPoint point( 1, TouchPoint::Motion, 102.0f, 102.0f );
+
+ DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchHover, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION );
+ DALI_TEST_EQUALS( hoverEvent.GetPointCount(), 1u, TEST_LOCATION );
+ DALI_TEST_EQUALS( hoverEvent.points[0].deviceId, point.deviceId, TEST_LOCATION );
+ DALI_TEST_EQUALS( hoverEvent.points[0].state, point.state, TEST_LOCATION );
+ DALI_TEST_EQUALS( hoverEvent.points[0].screen, point.screen, TEST_LOCATION );
+ }
+
+ time++;
+
+ // Motion event
+ {
+ Integration::TouchEvent touchEvent;
+ Integration::HoverEvent hoverEvent;
+ TouchPoint point( 1, TouchPoint::Motion, 103.0f, 103.0f );
+
+ DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchHover, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION );
+ DALI_TEST_EQUALS( hoverEvent.GetPointCount(), 1u, TEST_LOCATION );
+ DALI_TEST_EQUALS( hoverEvent.points[0].deviceId, point.deviceId, TEST_LOCATION );
+ DALI_TEST_EQUALS( hoverEvent.points[0].state, point.state, TEST_LOCATION );
+ DALI_TEST_EQUALS( hoverEvent.points[0].screen, point.screen, TEST_LOCATION );
+ }
+
+ time++;
+
+ // Down event
+ {
+ Integration::TouchEvent touchEvent;
+ Integration::HoverEvent hoverEvent;
+ TouchPoint point( 1, TouchPoint::Down, 103.0f, 103.0f );
+
+ DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchBoth, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION );
+ DALI_TEST_EQUALS( touchEvent.GetPointCount(), 1u, TEST_LOCATION );
+ DALI_TEST_EQUALS( touchEvent.points[0].deviceId, point.deviceId, TEST_LOCATION );
+ DALI_TEST_EQUALS( touchEvent.points[0].state, point.state, TEST_LOCATION );
+ DALI_TEST_EQUALS( touchEvent.points[0].screen, point.screen, TEST_LOCATION );
+ DALI_TEST_EQUALS( hoverEvent.GetPointCount(), 1u, TEST_LOCATION );
+ DALI_TEST_EQUALS( hoverEvent.points[0].deviceId, point.deviceId, TEST_LOCATION );
+ DALI_TEST_EQUALS( hoverEvent.points[0].state, TouchPoint::Finished, TEST_LOCATION );
+ DALI_TEST_EQUALS( hoverEvent.points[0].screen, point.screen, TEST_LOCATION );
}
END_TEST;
}
// Down event
{
Integration::TouchEvent touchEvent;
+ Integration::HoverEvent hoverEvent;
TouchPoint point( 1, TouchPoint::Down, 100.0f, 100.0f );
- DALI_TEST_EQUALS( true, combiner.GetNextTouchEvent( point, time, touchEvent ), TEST_LOCATION );
+ DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchTouch, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION );
DALI_TEST_EQUALS( touchEvent.GetPointCount(), 1u, TEST_LOCATION );
DALI_TEST_EQUALS( touchEvent.points[0].deviceId, point.deviceId, TEST_LOCATION );
DALI_TEST_EQUALS( touchEvent.points[0].state, point.state, TEST_LOCATION );
// Another down with the same ID
{
Integration::TouchEvent touchEvent;
+ Integration::HoverEvent hoverEvent;
TouchPoint point( 1, TouchPoint::Down, 100.0f, 100.0f );
- DALI_TEST_EQUALS( false, combiner.GetNextTouchEvent( point, time, touchEvent ), TEST_LOCATION );
+ DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchNone, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION );
}
END_TEST;
}
// Up event
{
Integration::TouchEvent touchEvent;
+ Integration::HoverEvent hoverEvent;
TouchPoint point( 1, TouchPoint::Up, 100.0f, 100.0f );
- DALI_TEST_EQUALS( false, combiner.GetNextTouchEvent( point, time, touchEvent ), TEST_LOCATION );
+ DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchNone, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION );
}
time++;
// Up event
{
Integration::TouchEvent touchEvent;
+ Integration::HoverEvent hoverEvent;
TouchPoint point( 1, TouchPoint::Up, 102.0f, 102.0f );
- DALI_TEST_EQUALS( false, combiner.GetNextTouchEvent( point, time, touchEvent ), TEST_LOCATION );
+ DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchNone, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION );
}
END_TEST;
}
// Down event
{
Integration::TouchEvent touchEvent;
+ Integration::HoverEvent hoverEvent;
TouchPoint point( 1, TouchPoint::Down, 100.0f, 100.0f );
- DALI_TEST_EQUALS( true, combiner.GetNextTouchEvent( point, time, touchEvent ), TEST_LOCATION );
+ DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchTouch, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION );
DALI_TEST_EQUALS( touchEvent.GetPointCount(), 1u, TEST_LOCATION );
DALI_TEST_EQUALS( touchEvent.points[0].deviceId, point.deviceId, TEST_LOCATION );
DALI_TEST_EQUALS( touchEvent.points[0].state, point.state, TEST_LOCATION );
// Up event
{
Integration::TouchEvent touchEvent;
+ Integration::HoverEvent hoverEvent;
TouchPoint point( 1, TouchPoint::Up, 100.0f, 100.0f );
- DALI_TEST_EQUALS( true, combiner.GetNextTouchEvent( point, time, touchEvent ), TEST_LOCATION );
+ DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchTouch, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION );
DALI_TEST_EQUALS( touchEvent.GetPointCount(), 1u, TEST_LOCATION );
DALI_TEST_EQUALS( touchEvent.points[0].deviceId, point.deviceId, TEST_LOCATION );
DALI_TEST_EQUALS( touchEvent.points[0].state, point.state, TEST_LOCATION );
// Another up event
{
Integration::TouchEvent touchEvent;
+ Integration::HoverEvent hoverEvent;
TouchPoint point( 1, TouchPoint::Up, 100.0f, 100.0f );
- DALI_TEST_EQUALS( false, combiner.GetNextTouchEvent( point, time, touchEvent ), TEST_LOCATION );
+ DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchNone, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION );
}
END_TEST;
}
// Down event
{
Integration::TouchEvent touchEvent;
+ Integration::HoverEvent hoverEvent;
TouchPoint point( 1, TouchPoint::Down, 100.0f, 100.0f );
- DALI_TEST_EQUALS( true, combiner.GetNextTouchEvent( point, time, touchEvent ), TEST_LOCATION );
+ DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchTouch, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION );
DALI_TEST_EQUALS( touchEvent.GetPointCount(), 1u, TEST_LOCATION );
DALI_TEST_EQUALS( touchEvent.points[0].deviceId, point.deviceId, TEST_LOCATION );
DALI_TEST_EQUALS( touchEvent.points[0].state, point.state, TEST_LOCATION );
// Up event with different ID
{
Integration::TouchEvent touchEvent;
+ Integration::HoverEvent hoverEvent;
TouchPoint point( 2, TouchPoint::Up, 100.0f, 100.0f );
- DALI_TEST_EQUALS( false, combiner.GetNextTouchEvent( point, time, touchEvent ), TEST_LOCATION );
+ DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchNone, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION );
}
time++;
// Up event
{
Integration::TouchEvent touchEvent;
+ Integration::HoverEvent hoverEvent;
TouchPoint point( 1, TouchPoint::Up, 100.0f, 100.0f );
- DALI_TEST_EQUALS( true, combiner.GetNextTouchEvent( point, time, touchEvent ), TEST_LOCATION );
+ DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchTouch, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION );
DALI_TEST_EQUALS( touchEvent.GetPointCount(), 1u, TEST_LOCATION );
DALI_TEST_EQUALS( touchEvent.points[0].deviceId, point.deviceId, TEST_LOCATION );
DALI_TEST_EQUALS( touchEvent.points[0].state, point.state, TEST_LOCATION );
// Down event
{
Integration::TouchEvent touchEvent;
+ Integration::HoverEvent hoverEvent;
TouchPoint point( 1, TouchPoint::Down, 100.0f, 100.0f );
- DALI_TEST_EQUALS( true, combiner.GetNextTouchEvent( point, time, touchEvent ), TEST_LOCATION );
+ DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchTouch, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION );
DALI_TEST_EQUALS( touchEvent.GetPointCount(), 1u, TEST_LOCATION );
DALI_TEST_EQUALS( touchEvent.points[0].deviceId, point.deviceId, TEST_LOCATION );
DALI_TEST_EQUALS( touchEvent.points[0].state, point.state, TEST_LOCATION );
// Motion event with different ID
{
Integration::TouchEvent touchEvent;
+ Integration::HoverEvent hoverEvent;
TouchPoint point( 2, TouchPoint::Motion, 100.0f, 100.0f );
- DALI_TEST_EQUALS( false, combiner.GetNextTouchEvent( point, time, touchEvent ), TEST_LOCATION );
+ DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchHover, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION );
+ DALI_TEST_EQUALS( hoverEvent.GetPointCount(), 1u, TEST_LOCATION );
+ DALI_TEST_EQUALS( hoverEvent.points[0].deviceId, point.deviceId, TEST_LOCATION );
+ DALI_TEST_EQUALS( hoverEvent.points[0].state, TouchPoint::Started, TEST_LOCATION );
+ DALI_TEST_EQUALS( hoverEvent.points[0].screen, point.screen, TEST_LOCATION );
}
time++;
// Motion event
{
Integration::TouchEvent touchEvent;
+ Integration::HoverEvent hoverEvent;
TouchPoint point( 1, TouchPoint::Motion, 102.0f, 102.0f );
- DALI_TEST_EQUALS( true, combiner.GetNextTouchEvent( point, time, touchEvent ), TEST_LOCATION );
+ DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchTouch, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION );
DALI_TEST_EQUALS( touchEvent.GetPointCount(), 1u, TEST_LOCATION );
DALI_TEST_EQUALS( touchEvent.points[0].deviceId, point.deviceId, TEST_LOCATION );
DALI_TEST_EQUALS( touchEvent.points[0].state, point.state, TEST_LOCATION );
// 1st point down
{
Integration::TouchEvent touchEvent;
+ Integration::HoverEvent hoverEvent;
TouchPoint point( 1, TouchPoint::Down, 100.0f, 100.0f );
- DALI_TEST_EQUALS( true, combiner.GetNextTouchEvent( point, time, touchEvent ), TEST_LOCATION );
+ DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchTouch, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION );
DALI_TEST_EQUALS( touchEvent.GetPointCount(), 1u, TEST_LOCATION );
DALI_TEST_EQUALS( touchEvent.points[0].deviceId, point.deviceId, TEST_LOCATION );
DALI_TEST_EQUALS( touchEvent.points[0].state, point.state, TEST_LOCATION );
// 2nd point down
{
Integration::TouchEvent touchEvent;
+ Integration::HoverEvent hoverEvent;
TouchPoint point( 2, TouchPoint::Down, 200.0f, 200.0f );
- DALI_TEST_EQUALS( true, combiner.GetNextTouchEvent( point, time, touchEvent ), TEST_LOCATION );
+ DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchTouch, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION );
DALI_TEST_EQUALS( touchEvent.GetPointCount(), 2u, TEST_LOCATION );
DALI_TEST_EQUALS( touchEvent.points[1].deviceId, point.deviceId, TEST_LOCATION );
DALI_TEST_EQUALS( touchEvent.points[0].state, TouchPoint::Stationary, TEST_LOCATION );
// 1st point motion
{
Integration::TouchEvent touchEvent;
+ Integration::HoverEvent hoverEvent;
TouchPoint point( 1, TouchPoint::Motion, 101.0f, 100.0f );
- DALI_TEST_EQUALS( true, combiner.GetNextTouchEvent( point, time, touchEvent ), TEST_LOCATION );
+ DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchTouch, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION );
DALI_TEST_EQUALS( touchEvent.GetPointCount(), 2u, TEST_LOCATION );
DALI_TEST_EQUALS( touchEvent.points[0].deviceId, point.deviceId, TEST_LOCATION );
DALI_TEST_EQUALS( touchEvent.points[0].state, point.state, TEST_LOCATION );
// 2nd point motion, no time diff
{
Integration::TouchEvent touchEvent;
+ Integration::HoverEvent hoverEvent;
TouchPoint point( 2, TouchPoint::Motion, 200.0f, 200.0f );
- DALI_TEST_EQUALS( false, combiner.GetNextTouchEvent( point, time, touchEvent ), TEST_LOCATION );
+ DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchNone, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION );
}
time++;
// 2nd point motion
{
Integration::TouchEvent touchEvent;
+ Integration::HoverEvent hoverEvent;
TouchPoint point( 2, TouchPoint::Motion, 201.0f, 201.0f );
- DALI_TEST_EQUALS( true, combiner.GetNextTouchEvent( point, time, touchEvent ), TEST_LOCATION );
+ DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchTouch, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION );
DALI_TEST_EQUALS( touchEvent.GetPointCount(), 2u, TEST_LOCATION );
DALI_TEST_EQUALS( touchEvent.points[1].deviceId, point.deviceId, TEST_LOCATION );
DALI_TEST_EQUALS( touchEvent.points[0].state, TouchPoint::Stationary, TEST_LOCATION );
// 1st point up
{
Integration::TouchEvent touchEvent;
+ Integration::HoverEvent hoverEvent;
TouchPoint point( 1, TouchPoint::Up, 101.0f, 100.0f );
- DALI_TEST_EQUALS( true, combiner.GetNextTouchEvent( point, time, touchEvent ), TEST_LOCATION );
+ DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchTouch, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION );
DALI_TEST_EQUALS( touchEvent.GetPointCount(), 2u, TEST_LOCATION );
DALI_TEST_EQUALS( touchEvent.points[0].deviceId, point.deviceId, TEST_LOCATION );
DALI_TEST_EQUALS( touchEvent.points[0].state, point.state, TEST_LOCATION );
// 2nd point motion
{
Integration::TouchEvent touchEvent;
+ Integration::HoverEvent hoverEvent;
TouchPoint point( 2, TouchPoint::Motion, 202.0f, 202.0f );
- DALI_TEST_EQUALS( true, combiner.GetNextTouchEvent( point, time, touchEvent ), TEST_LOCATION );
+ DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchTouch, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION );
DALI_TEST_EQUALS( touchEvent.GetPointCount(), 1u, TEST_LOCATION );
DALI_TEST_EQUALS( touchEvent.points[0].deviceId, point.deviceId, TEST_LOCATION );
DALI_TEST_EQUALS( touchEvent.points[0].state, point.state, TEST_LOCATION );
// 2nd point up
{
Integration::TouchEvent touchEvent;
+ Integration::HoverEvent hoverEvent;
TouchPoint point( 2, TouchPoint::Up, 202.0f, 202.0f );
- DALI_TEST_EQUALS( true, combiner.GetNextTouchEvent( point, time, touchEvent ), TEST_LOCATION );
+ DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchTouch, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION );
DALI_TEST_EQUALS( touchEvent.GetPointCount(), 1u, TEST_LOCATION );
DALI_TEST_EQUALS( touchEvent.points[0].deviceId, point.deviceId, TEST_LOCATION );
DALI_TEST_EQUALS( touchEvent.points[0].state, point.state, TEST_LOCATION );
for ( unsigned int pointCount = 1u; pointCount < maximum; ++pointCount )
{
Integration::TouchEvent touchEvent;
+ Integration::HoverEvent hoverEvent;
TouchPoint point( pointCount, TouchPoint::Down, 100.0f, 100.0f );
- DALI_TEST_EQUALS( true, combiner.GetNextTouchEvent( point, time++, touchEvent ), TEST_LOCATION );
+ DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchTouch, combiner.GetNextTouchEvent( point, time++, touchEvent, hoverEvent ), TEST_LOCATION );
DALI_TEST_EQUALS( touchEvent.GetPointCount(), pointCount, TEST_LOCATION );
}
for ( unsigned int pointCount = maximum - 1; pointCount > 0; --pointCount )
{
Integration::TouchEvent touchEvent;
+ Integration::HoverEvent hoverEvent;
TouchPoint point( pointCount, TouchPoint::Up, 100.0f, 100.0f );
- DALI_TEST_EQUALS( true, combiner.GetNextTouchEvent( point, time++, touchEvent ), TEST_LOCATION );
+ DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchTouch, combiner.GetNextTouchEvent( point, time++, touchEvent, hoverEvent ), TEST_LOCATION );
DALI_TEST_EQUALS( touchEvent.GetPointCount(), pointCount, TEST_LOCATION );
}
END_TEST;
// Down event
{
Integration::TouchEvent touchEvent;
+ Integration::HoverEvent hoverEvent;
TouchPoint point( 1, TouchPoint::Down, 100.0f, 100.0f );
- DALI_TEST_EQUALS( true, combiner.GetNextTouchEvent( point, time, touchEvent ), TEST_LOCATION );
+ DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchTouch, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION );
DALI_TEST_EQUALS( touchEvent.GetPointCount(), 1u, TEST_LOCATION );
DALI_TEST_EQUALS( touchEvent.points[0].deviceId, point.deviceId, TEST_LOCATION );
DALI_TEST_EQUALS( touchEvent.points[0].state, point.state, TEST_LOCATION );
// Up event
{
Integration::TouchEvent touchEvent;
+ Integration::HoverEvent hoverEvent;
TouchPoint point( 1, TouchPoint::Up, 100.0f, 100.0f );
- DALI_TEST_EQUALS( false, combiner.GetNextTouchEvent( point, time, touchEvent ), TEST_LOCATION );
+ DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchNone, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION );
}
END_TEST;
}
// Down event
{
Integration::TouchEvent touchEvent;
+ Integration::HoverEvent hoverEvent;
TouchPoint point( 1, TouchPoint::Down, 100.0f, 100.0f );
- DALI_TEST_EQUALS( true, combiner.GetNextTouchEvent( point, time, touchEvent ), TEST_LOCATION );
+ DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchTouch, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION );
DALI_TEST_EQUALS( touchEvent.GetPointCount(), 1u, TEST_LOCATION );
DALI_TEST_EQUALS( touchEvent.points[0].deviceId, point.deviceId, TEST_LOCATION );
DALI_TEST_EQUALS( touchEvent.points[0].state, point.state, TEST_LOCATION );
// Interrupted event
{
Integration::TouchEvent touchEvent;
+ Integration::HoverEvent hoverEvent;
TouchPoint point( 1, TouchPoint::Interrupted, 100.0f, 100.0f );
- DALI_TEST_EQUALS( true, combiner.GetNextTouchEvent( point, time, touchEvent ), TEST_LOCATION );
+ DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchBoth, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION );
DALI_TEST_EQUALS( touchEvent.GetPointCount(), 1u, TEST_LOCATION );
DALI_TEST_EQUALS( touchEvent.points[0].state, point.state, TEST_LOCATION );
+ DALI_TEST_EQUALS( hoverEvent.GetPointCount(), 1u, TEST_LOCATION );
+ DALI_TEST_EQUALS( hoverEvent.points[0].state, point.state, TEST_LOCATION );
}
// Send up, should not be able to send as combiner has been reset.
// Up event
{
Integration::TouchEvent touchEvent;
+ Integration::HoverEvent hoverEvent;
TouchPoint point( 1, TouchPoint::Up, 100.0f, 100.0f );
- DALI_TEST_EQUALS( false, combiner.GetNextTouchEvent( point, time, touchEvent ), TEST_LOCATION );
+ DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchNone, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION );
}
END_TEST;
}
for ( unsigned int pointCount = 1u; pointCount < maximum; ++pointCount )
{
Integration::TouchEvent touchEvent;
+ Integration::HoverEvent hoverEvent;
TouchPoint point( pointCount, TouchPoint::Down, 100.0f, 100.0f );
- DALI_TEST_EQUALS( true, combiner.GetNextTouchEvent( point, time++, touchEvent ), TEST_LOCATION );
+ DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchTouch, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION );
DALI_TEST_EQUALS( touchEvent.GetPointCount(), pointCount, TEST_LOCATION );
}
// Interrupted event
{
Integration::TouchEvent touchEvent;
+ Integration::HoverEvent hoverEvent;
TouchPoint point( 1, TouchPoint::Interrupted, 100.0f, 100.0f );
- DALI_TEST_EQUALS( true, combiner.GetNextTouchEvent( point, time, touchEvent ), TEST_LOCATION );
+ DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchBoth, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION );
DALI_TEST_EQUALS( touchEvent.GetPointCount(), 1u, TEST_LOCATION );
DALI_TEST_EQUALS( touchEvent.points[0].state, point.state, TEST_LOCATION );
+ DALI_TEST_EQUALS( hoverEvent.GetPointCount(), 1u, TEST_LOCATION );
+ DALI_TEST_EQUALS( hoverEvent.points[0].state, point.state, TEST_LOCATION );
}
// Send up, should not be able to send as combiner has been reset.
// Up event
{
Integration::TouchEvent touchEvent;
+ Integration::HoverEvent hoverEvent;
TouchPoint point( 1, TouchPoint::Up, 100.0f, 100.0f );
- DALI_TEST_EQUALS( false, combiner.GetNextTouchEvent( point, time, touchEvent ), TEST_LOCATION );
+ DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchNone, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION );
}
END_TEST;
}
// Stationary event
{
Integration::TouchEvent touchEvent;
+ Integration::HoverEvent hoverEvent;
TouchPoint point( 1, TouchPoint::Stationary, 100.0f, 100.0f );
- DALI_TEST_EQUALS( false, combiner.GetNextTouchEvent( point, time, touchEvent ), TEST_LOCATION );
+ DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchNone, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION );
}
END_TEST;
}
Touch, ///< A touch event, when the user interacts with the screen.
Key, ///< A key pressed event, from the virtual or external keyboard.
Gesture, ///< A Gesture event has been detected.
- MouseWheel ///< A mouse wheel event, when the mouse wheel is being rolled from an external mouse.
+ MouseWheel, ///< A mouse wheel event, when the mouse wheel is being rolled from an external mouse.
+ Hover ///< A hover event, when the user hovers above the screen.
};
// Data
--- /dev/null
+/*
+ * Copyright (c) 2014 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/integration-api/events/hover-event-integ.h>
+
+namespace Dali
+{
+
+namespace Integration
+{
+
+HoverEvent::HoverEvent()
+: MultiPointEvent( Hover )
+{
+}
+
+HoverEvent::HoverEvent( unsigned long time )
+: MultiPointEvent( Hover, time )
+{
+}
+
+HoverEvent::~HoverEvent()
+{
+}
+
+} // namespace Integration
+
+} // namespace Dali
--- /dev/null
+#ifndef __DALI_INTEGRATION_HOVER_EVENT_H__
+#define __DALI_INTEGRATION_HOVER_EVENT_H__
+
+/*
+ * Copyright (c) 2014 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/events/hover-event.h>
+#include <dali/integration-api/events/multi-point-event-integ.h>
+
+namespace Dali DALI_IMPORT_API
+{
+
+namespace Integration
+{
+
+/**
+ * An instance of this structure should be used by the adaptor to send a hover event to Dali core.
+ *
+ * This class can contain one or many touch points. It also contains the time at which the
+ * event occurred.
+ */
+struct HoverEvent : public MultiPointEvent
+{
+ // Construction & Destruction
+
+ /**
+ * Default Constructor
+ */
+ HoverEvent();
+
+ /**
+ * Constructor
+ * @param[in] time The time the event occurred.
+ */
+ HoverEvent(unsigned long time);
+
+ /**
+ * Virtual destructor
+ */
+ virtual ~HoverEvent();
+};
+
+} // namespace Integration
+
+} // namespace Dali
+
+#endif // __DALI_INTEGRATION_HOVER_EVENT_H__
--- /dev/null
+/*
+ * Copyright (c) 2014 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/integration-api/events/multi-point-event-integ.h>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-common.h>
+
+namespace Dali
+{
+
+namespace Integration
+{
+
+MultiPointEvent::MultiPointEvent( Type eventType )
+: Event( eventType ),
+ time( 0 )
+{
+}
+
+MultiPointEvent::MultiPointEvent( Type eventType, unsigned long time )
+: Event( eventType ),
+ time( time )
+{
+}
+
+MultiPointEvent::~MultiPointEvent()
+{
+}
+
+void MultiPointEvent::AddPoint(const TouchPoint& point)
+{
+ points.push_back(point);
+}
+
+TouchPoint& MultiPointEvent::GetPoint(unsigned int point)
+{
+ DALI_ASSERT_ALWAYS(point < points.size() && "MultiPointEvent: Point index out of bounds");
+ return points[point];
+}
+
+const TouchPoint& MultiPointEvent::GetPoint(unsigned int point) const
+{
+ DALI_ASSERT_ALWAYS(point < points.size() && "MultiPointEvent: Point index out of bounds");
+ return points[point];
+}
+
+unsigned int MultiPointEvent::GetPointCount() const
+{
+ return points.size();
+}
+
+} // namespace Integration
+
+} // namespace Dali
--- /dev/null
+#ifndef __DALI_INTEGRATION_MULTI_POINT_EVENT_H__
+#define __DALI_INTEGRATION_MULTI_POINT_EVENT_H__
+
+/*
+ * Copyright (c) 2014 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/vector-wrapper.h>
+#include <dali/integration-api/events/event.h>
+#include <dali/public-api/events/touch-point.h>
+
+namespace Dali DALI_IMPORT_API
+{
+
+namespace Integration
+{
+
+/**
+ * An instance of this structure should be used by the adaptor to send a multi-point event to Dali core.
+ *
+ * This class can contain one or multiple touch points. It also contains the time at which the
+ * event occurred.
+ */
+struct MultiPointEvent : public Event
+{
+ // Construction & Destruction
+
+public:
+ /**
+ * Virtual destructor
+ */
+ virtual ~MultiPointEvent();
+
+protected:
+ /**
+ * Default Constructor
+ */
+ MultiPointEvent(Type eventType);
+
+ /**
+ * Constructor
+ * @param[in] time The time the event occurred.
+ */
+ MultiPointEvent(Type eventType, unsigned long time);
+
+public:
+ // Data
+
+ /**
+ * @copydoc Dali::MultiPointEvent::points
+ */
+ std::vector<TouchPoint> points;
+
+ /**
+ * @copydoc Dali::MultiPointEvent::time
+ */
+ unsigned long time;
+
+ // Convenience Methods
+
+ /**
+ * Adds a point to the MultiPointEvent.
+ * @param[in] point The point to add.
+ */
+ void AddPoint(const TouchPoint& point);
+
+ /**
+ * @copydoc Dali::MultiPointEvent::GetPoint()
+ */
+ TouchPoint& GetPoint(unsigned int point);
+
+ /**
+ * @copydoc Dali::MultiPointEvent::GetPoint()
+ */
+ const TouchPoint& GetPoint(unsigned int point) const;
+
+ /**
+ * @copydoc Dali::MultiPointEvent::GetPointCount() const
+ */
+ unsigned int GetPointCount() const;
+};
+
+} // namespace Integration
+
+} // namespace Dali
+
+#endif // __DALI_INTEGRATION_MULTI_POINT_EVENT_H__
// INTERNAL INCLUDES
#include <dali/integration-api/events/touch-event-integ.h>
+#include <dali/integration-api/events/hover-event-integ.h>
#include <dali/public-api/common/dali-common.h>
namespace Dali
{
}
-bool TouchEventCombiner::GetNextTouchEvent( const TouchPoint& point, unsigned long time, TouchEvent& touchEvent )
+TouchEventCombiner::EventDispatchType TouchEventCombiner::GetNextTouchEvent( const TouchPoint& point, unsigned long time, TouchEvent& touchEvent, HoverEvent& hoverEvent )
{
- bool dispatchEvent( false );
+ TouchEventCombiner::EventDispatchType dispatchEvent( TouchEventCombiner::DispatchNone );
switch ( point.state )
{
- case TouchPoint::Down:
+ case TouchPoint::Started:
{
touchEvent.time = time;
bool addToContainer( true );
{
mPressedPoints.push_back( PointInfo( point, time ) );
touchEvent.AddPoint( point );
- dispatchEvent = true; // Only dispatch event if just added to container
+ dispatchEvent = TouchEventCombiner::DispatchTouch; // Only dispatch touch event if just added to container
+
+ // Check whether hover event was dispatched previously
+ if ( !mHoveredPoints.empty() )
+ {
+ hoverEvent.time = time;
+
+ PointInfoContainer::iterator match( mHoveredPoints.end() );
+ for ( PointInfoContainer::iterator iter = mHoveredPoints.begin(), endIter = mHoveredPoints.end(); iter != endIter; ++iter )
+ {
+ if ( point.deviceId == iter->point.deviceId )
+ {
+ match = iter;
+ // Add new point to the HoverEvent
+ iter->point.state = TouchPoint::Finished;
+ hoverEvent.AddPoint( iter->point );
+ }
+ else
+ {
+ iter->point.state = TouchPoint::Stationary;
+ hoverEvent.AddPoint( iter->point );
+ }
+ }
+
+ if ( match != mHoveredPoints.end() )
+ {
+ mHoveredPoints.erase( match );
+ dispatchEvent = TouchEventCombiner::DispatchBoth; // We should only dispatch hover events if the point was actually hovered in this window
+ }
+ }
}
break;
}
- case TouchPoint::Up:
+ case TouchPoint::Finished:
{
touchEvent.time = time;
if ( match != mPressedPoints.end() )
{
mPressedPoints.erase( match );
- dispatchEvent = true; // We should only dispatch events if the point was actually pressed in this window
+ dispatchEvent = TouchEventCombiner::DispatchTouch; // We should only dispatch touch events if the point was actually pressed in this window
+
+ // Iterate through already stored touch points for HoverEvent and delete them
+ for ( PointInfoContainer::iterator iter = mHoveredPoints.begin(), endIter = mHoveredPoints.end(); iter != endIter; ++iter )
+ {
+ if ( iter->point.deviceId == point.deviceId )
+ {
+ mHoveredPoints.erase( iter );
+ }
+ }
}
break;
}
case TouchPoint::Motion:
{
+ bool fromNewDeviceId = false;
+
if ( !mPressedPoints.empty() )
{
touchEvent.time = time;
+ bool ignore = false;
PointInfoContainer::iterator match = mPressedPoints.end();
for ( PointInfoContainer::iterator iter = mPressedPoints.begin(), endIter = mPressedPoints.end(); iter != endIter; ++iter )
{
if ( timeDiff < mMinMotionTime )
{
// Motion event sent too soon after previous event so ignore
+ ignore = true;
break;
}
( abs( point.screen.y - iter->point.screen.y ) < mMinMotionDistance.y ) )
{
// Not enough positional change from last event so ignore
+ ignore = true;
break;
}
PointInfo matchedPoint( point, time );
std::swap( *match, matchedPoint );
- dispatchEvent = true;
+ dispatchEvent = TouchEventCombiner::DispatchTouch; // Dispatch touch event
+ }
+ else if(!ignore)
+ {
+ fromNewDeviceId = true;
+ }
+ }
+
+ // Dispatch hover event if no previous down event received or the motion event comes from a new device ID
+ if(mPressedPoints.empty() || fromNewDeviceId)
+ {
+ hoverEvent.time = time;
+
+ // Iterate through already stored touch points and add to HoverEvent
+ bool ignore = false;
+ PointInfoContainer::iterator match = mHoveredPoints.end();
+ for ( PointInfoContainer::iterator iter = mHoveredPoints.begin(), endIter = mHoveredPoints.end(); iter != endIter; ++iter )
+ {
+ if ( iter->point.deviceId == point.deviceId )
+ {
+ unsigned long timeDiff( time - iter->time );
+
+ if ( timeDiff < mMinMotionTime )
+ {
+ // Motion event sent too soon after previous event so ignore
+ ignore = true;
+ break;
+ }
+
+ if ( ( abs( point.screen.x - iter->point.screen.x ) < mMinMotionDistance.x ) &&
+ ( abs( point.screen.y - iter->point.screen.y ) < mMinMotionDistance.y ) )
+ {
+ // Not enough positional change from last event so ignore
+ ignore = true;
+ break;
+ }
+
+ match = iter;
+
+ // Add new touch point to the HoverEvent
+ hoverEvent.AddPoint( point );
+ }
+ else
+ {
+ iter->point.state = TouchPoint::Stationary;
+ hoverEvent.AddPoint( iter->point );
+ }
+ }
+
+ // Add new hover point to the list and to the HoverEvent
+ if ( !ignore ) // Only dispatch hover event when it should not be ignored
+ {
+ if( match == mHoveredPoints.end() )
+ {
+ TouchPoint hoverPoint(point);
+ hoverPoint.state = TouchPoint::Started; // The first hover event received
+ mHoveredPoints.push_back( PointInfo( hoverPoint, time ) );
+ hoverEvent.AddPoint( hoverPoint );
+ }
+ else
+ {
+ PointInfo matchedPoint( point, time );
+ std::swap( *match, matchedPoint );
+ }
+
+ if(dispatchEvent == TouchEventCombiner::DispatchTouch)
+ {
+ dispatchEvent = TouchEventCombiner::DispatchBoth;
+ }
+ else
+ {
+ dispatchEvent = TouchEventCombiner::DispatchHover;
+ }
}
}
break;
// We should still tell core about the interruption.
touchEvent.AddPoint( point );
- dispatchEvent = true;
+ hoverEvent.AddPoint( point );
+ dispatchEvent = TouchEventCombiner::DispatchBoth;
break;
}
void TouchEventCombiner::Reset()
{
mPressedPoints.clear();
+ mHoveredPoints.clear();
}
} // namespace Integration
{
struct TouchEvent;
+struct HoverEvent;
/**
* Dali::Integration::TouchEventCombiner is a utility class, an instance of which, should be created
* upon initialisation. It accepts single Point(s) containing information about a touch area and
- * creates a TouchEvent combining the latest event's information with previous TouchPoint(s).
+ * creates a TouchEvent and/or HoverEvent combining the latest event's information with previous TouchPoint(s).
*
- * The created TouchEvent can then be sent to the Dali Core as indicated by the GetNextTouchEvent()
+ * The created TouchEvent and/or HoverEvent can then be sent to the Dali Core as indicated by the GetNextTouchEvent()
* method.
*
* The TouchEventCombiner ensures that the following rules are also adhered to:
{
public:
+ // Enumerations
+
+ enum EventDispatchType
+ {
+ DispatchTouch, ///< The touch event should be dispatched.
+ DispatchHover, ///< The hover event should be dispatched.
+ DispatchBoth, ///< Both touch event and hover event should be dispatched.
+ DispatchNone ///< Neither touch event nor hover event should be dispatched.
+ };
+
/**
* Default Constructor.
* @note The default minimum motion time is 1 ms between motion events and the default behaviour
public:
/**
- * Allows the caller to pass in a point which is processed and the TouchEvent is appropriately filled with the new,
+ * Allows the caller to pass in a point which is processed and the TouchEvent and/or HoverEvent is appropriately filled with the new,
* and previously stored Point information.
*
- * @note If the thresholds set have not been passed, then false is returned and the TouchEvent should not be sent
+ * @note If the thresholds set have not been passed, then false is returned and the TouchEvent and/or HoverEvent should not be sent
* to Dali Core.
*
* @param[in] point The new Point.
* @param[in] time The time the event occurred.
* @param[out] touchEvent This is populated with the correct Point(s) and time information.
+ * @param[out] hoverEvent This is populated with the correct Point(s) and time information.
*
* @return true if the point is beyond the different thresholds set thus, should be sent to core, false otherwise.
*/
- bool GetNextTouchEvent( const TouchPoint& point, unsigned long time, TouchEvent& touchEvent );
+ EventDispatchType GetNextTouchEvent( const TouchPoint& point, unsigned long time, TouchEvent& touchEvent, HoverEvent& hoverEvent );
/**
* Sets the minimum time (in ms) that should occur between motion events.
struct PointInfo;
typedef std::vector< PointInfo > PointInfoContainer;
- PointInfoContainer mPressedPoints; ///< A container of point and time.
+ PointInfoContainer mPressedPoints; ///< A container of touched point and time.
+ PointInfoContainer mHoveredPoints; ///< A container of hovered point and time.
unsigned long mMinMotionTime; ///< The minimum time that should elapse before considering a new motion event.
Vector2 mMinMotionDistance; ///< The minimum distance in the X and Y direction before considering a new motion event.
// CLASS HEADER
#include <dali/integration-api/events/touch-event-integ.h>
-// INTERNAL INCLUDES
-#include <dali/public-api/common/dali-common.h>
-
namespace Dali
{
{
TouchEvent::TouchEvent()
-: Event(Touch),
- time(0)
+: MultiPointEvent( Touch )
{
}
-TouchEvent::TouchEvent(unsigned long time)
-: Event(Touch),
- time(time)
+TouchEvent::TouchEvent( unsigned long time )
+: MultiPointEvent( Touch, time )
{
}
{
}
-void TouchEvent::AddPoint(const TouchPoint& point)
-{
- points.push_back(point);
-}
-
-TouchPoint& TouchEvent::GetPoint(unsigned int point)
-{
- DALI_ASSERT_ALWAYS(point < points.size() && "TouchEvent: Point index out of bounds");
- return points[point];
-}
-
-const TouchPoint& TouchEvent::GetPoint(unsigned int point) const
-{
- DALI_ASSERT_ALWAYS(point < points.size() && "TouchEvent: Point index out of bounds");
- return points[point];
-}
-
-unsigned int TouchEvent::GetPointCount() const
-{
- return points.size();
-}
-
} // namespace Integration
} // namespace Dali
*/
// INTERNAL INCLUDES
-#include <dali/public-api/common/vector-wrapper.h>
-#include <dali/integration-api/events/event.h>
#include <dali/public-api/events/touch-event.h>
-#include <dali/public-api/events/touch-point.h>
+#include <dali/integration-api/events/multi-point-event-integ.h>
namespace Dali DALI_IMPORT_API
{
* This class can contain one or many touch points. It also contains the time at which the
* event occurred.
*/
-struct TouchEvent : public Event
+struct TouchEvent : public MultiPointEvent
{
// Construction & Destruction
* Virtual destructor
*/
virtual ~TouchEvent();
-
- // Data
-
- /**
- * @copydoc Dali::TouchEvent::points
- */
- std::vector<TouchPoint> points;
-
- /**
- * @copydoc Dali::TouchEvent::time
- */
- unsigned long time;
-
- // Convenience Methods
-
- /**
- * Adds a point to the TouchEvent.
- * @param[in] point The point to add.
- */
- void AddPoint(const TouchPoint& point);
-
- /**
- * @copydoc Dali::TouchEvent::GetPoint()
- */
- TouchPoint& GetPoint(unsigned int point);
-
- /**
- * @copydoc Dali::TouchEvent::GetPoint()
- */
- const TouchPoint& GetPoint(unsigned int point) const;
-
- /**
- * @copydoc Dali::TouchEvent::GetPointCount() const
- */
- unsigned int GetPointCount() const;
};
} // namespace Integration
$(platform_abstraction_src_dir)/common/lockless-buffer.cpp \
$(platform_abstraction_src_dir)/events/event.cpp \
$(platform_abstraction_src_dir)/events/gesture-event.cpp \
+ $(platform_abstraction_src_dir)/events/hover-event-integ.cpp \
$(platform_abstraction_src_dir)/events/key-event-integ.cpp \
$(platform_abstraction_src_dir)/events/long-press-gesture-event.cpp \
$(platform_abstraction_src_dir)/events/mouse-wheel-event-integ.cpp \
+ $(platform_abstraction_src_dir)/events/multi-point-event-integ.cpp \
$(platform_abstraction_src_dir)/events/pan-gesture-event.cpp \
$(platform_abstraction_src_dir)/events/pinch-gesture-event.cpp \
$(platform_abstraction_src_dir)/events/tap-gesture-event.cpp \
$(platform_abstraction_src_dir)/events/event.h \
$(platform_abstraction_src_dir)/events/gesture-event.h \
$(platform_abstraction_src_dir)/events/gesture-requests.h \
+ $(platform_abstraction_src_dir)/events/hover-event-integ.h \
$(platform_abstraction_src_dir)/events/key-event-integ.h \
$(platform_abstraction_src_dir)/events/long-press-gesture-event.h \
$(platform_abstraction_src_dir)/events/mouse-wheel-event-integ.h \
+ $(platform_abstraction_src_dir)/events/multi-point-event-integ.h \
$(platform_abstraction_src_dir)/events/pan-gesture-event.h \
$(platform_abstraction_src_dir)/events/pinch-gesture-event.h \
$(platform_abstraction_src_dir)/events/tap-gesture-event.h \
TypeRegistration mType( typeid(Dali::Actor), typeid(Dali::Handle), CreateActor );
SignalConnectorType signalConnector1(mType, Dali::Actor::SIGNAL_TOUCHED, &Actor::DoConnectSignal);
-SignalConnectorType signalConnector2(mType, Dali::Actor::SIGNAL_SET_SIZE, &Actor::DoConnectSignal);
-SignalConnectorType signalConnector3(mType, Dali::Actor::SIGNAL_ON_STAGE, &Actor::DoConnectSignal);
-SignalConnectorType signalConnector4(mType, Dali::Actor::SIGNAL_OFF_STAGE, &Actor::DoConnectSignal);
+SignalConnectorType signalConnector2(mType, Dali::Actor::SIGNAL_HOVERED, &Actor::DoConnectSignal);
+SignalConnectorType signalConnector3(mType, Dali::Actor::SIGNAL_SET_SIZE, &Actor::DoConnectSignal);
+SignalConnectorType signalConnector4(mType, Dali::Actor::SIGNAL_ON_STAGE, &Actor::DoConnectSignal);
+SignalConnectorType signalConnector5(mType, Dali::Actor::SIGNAL_OFF_STAGE, &Actor::DoConnectSignal);
TypeAction a1(mType, Dali::Actor::ACTION_SHOW, &Actor::DoAction);
TypeAction a2(mType, Dali::Actor::ACTION_HIDE, &Actor::DoAction);
return !mTouchedSignalV2.Empty() || mDerivedRequiresTouch;
}
+bool Actor::GetHoverRequired() const
+{
+ return !mHoveredSignalV2.Empty() || mDerivedRequiresHover;
+}
+
bool Actor::GetMouseWheelEventRequired() const
{
return !mMouseWheelEventSignalV2.Empty() || mDerivedRequiresMouseWheelEvent;
return consumed;
}
+bool Actor::EmitHoverEventSignal(const HoverEvent& event)
+{
+ bool consumed = false;
+
+ if ( !mHoveredSignalV2.Empty() )
+ {
+ Dali::Actor handle( this );
+ consumed = mHoveredSignalV2.Emit( handle, event );
+ }
+
+ if (!consumed)
+ {
+ // Notification for derived classes
+ consumed = OnHoverEvent( event );
+ }
+
+ return consumed;
+}
+
bool Actor::EmitMouseWheelEventSignal(const MouseWheelEvent& event)
{
bool consumed = false;
return mTouchedSignalV2;
}
+Dali::Actor::HoverSignalV2& Actor::HoveredSignal()
+{
+ return mHoveredSignalV2;
+}
+
Dali::Actor::MouseWheelEventSignalV2& Actor::MouseWheelEventSignal()
{
return mMouseWheelEventSignalV2;
{
actor->TouchedSignal().Connect( tracker, functor );
}
+ else if(Dali::Actor::SIGNAL_HOVERED == signalName)
+ {
+ actor->HoveredSignal().Connect( tracker, functor );
+ }
else if(Dali::Actor::SIGNAL_MOUSE_WHEEL_EVENT == signalName)
{
actor->MouseWheelEventSignal().Connect( tracker, functor );
mLeaveRequired( false ),
mKeyboardFocusable( false ),
mDerivedRequiresTouch( false ),
+ mDerivedRequiresHover( false ),
mDerivedRequiresMouseWheelEvent( false ),
mOnStageSignalled( false ),
mInheritRotation( true ),
struct KeyEvent;
struct TouchEvent;
+struct HoverEvent;
struct MouseWheelEvent;
namespace Internal
float GetCurrentOpacity() const;
/**
- * Sets whether an actor should emit touch signals; see SignalTouch().
+ * Sets whether an actor should emit touch or hover signals; see SignalTouch() and SignalHover().
* An actor is sensitive by default, which means that as soon as an application connects to the SignalTouch(),
- * the touch event signal will be emitted.
+ * the touch event signal will be emitted, and as soon as an application connects to the SignalHover(), the
+ * hover event signal will be emitted.
*
- * If the application wishes to temporarily disable the touch event signal emission, then they can do so by calling:
+ * If the application wishes to temporarily disable the touch or hover event signal emission, then they can do so by calling:
* @code
* actor.SetSensitive(false);
* @endcode
*
- * Then, to re-enable the touch event signal emission, the application should call:
+ * Then, to re-enable the touch or hover event signal emission, the application should call:
* @code
* actor.SetSensitive(true);
* @endcode
*
- * @see SignalTouch().
- * @note If an actor's sensitivity is set to false, then it's children will not emit a touch event signal either.
- * @param[in] sensitive true to enable emission of the touch event signals, false otherwise.
+ * @see SignalTouch() and SignalHover().
+ * @note If an actor's sensitivity is set to false, then it's children will not emit a touch or hover event signal either.
+ * @param[in] sensitive true to enable emission of the touch or hover event signals, false otherwise.
*/
void SetSensitive(bool sensitive)
{
}
/**
- * Query whether an actor emits touch event signals.
+ * Query whether an actor emits touch or hover event signals.
* @see SetSensitive(bool)
- * @return true, if emission of touch event signals is enabled, false otherwise.
+ * @return true, if emission of touch or hover event signals is enabled, false otherwise.
*/
bool IsSensitive() const
{
bool RayActorTest( const Vector4& rayOrigin, const Vector4& rayDir, Vector4& hitPointLocal, float& distance ) const;
/**
- * Sets whether the actor should receive a notification when touch motion events leave
+ * Sets whether the actor should receive a notification when touch or hover motion events leave
* the boundary of the actor.
*
* @note By default, this is set to false as most actors do not require this.
- * @note Need to connect to the SignalTouch to actually receive this event.
+ * @note Need to connect to the SignalTouch or SignalHover to actually receive this event.
*
* @param[in] required Should be set to true if a Leave event is required
*/
void SetLeaveRequired(bool required);
/**
- * This returns whether the actor requires touch events whenever touch motion events leave
+ * This returns whether the actor requires touch or hover events whenever touch or hover motion events leave
* the boundary of the actor.
* @return true if a Leave event is required, false otherwise.
*/
bool GetTouchRequired() const;
/**
+ * Query whether the application or derived actor type requires hover events.
+ * @return True if hover events are required.
+ */
+ bool GetHoverRequired() const;
+
+ /**
* Query whether the application or derived actor type requires mouse wheel events.
* @return True if mouse wheel events are required.
*/
bool EmitTouchEventSignal(const TouchEvent& event);
/**
+ * Used by the EventProcessor to emit hover event signals.
+ * @param[in] event The hover event.
+ * @return True if the event was consumed.
+ */
+ bool EmitHoverEventSignal(const HoverEvent& event);
+
+ /**
* Used by the EventProcessor to emit mouse wheel event signals.
* @param[in] event The mouse wheel event.
* @return True if the event was consumed.
Dali::Actor::TouchSignalV2& TouchedSignal();
/**
+ * @copydoc Dali::Actor::HoveredSignal()
+ */
+ Dali::Actor::HoverSignalV2& HoveredSignal();
+
+ /**
* @copydoc Dali::Actor::MouseWheelEventSignal()
*/
Dali::Actor::MouseWheelEventSignalV2& MouseWheelEventSignal();
/**
* For use in derived classes.
- * This is only called if mTouchRequired is true, and the touch-signal was not consumed.
+ * This is only called if mDerivedRequiresTouch is true, and the touch-signal was not consumed.
* @param[in] event The touch event.
* @return True if the event should be consumed.
*/
/**
* For use in derived classes.
+ * This is only called if mDerivedRequiresHover is true, and the hover-signal was not consumed.
+ * @param[in] event The hover event.
+ * @return True if the event should be consumed.
+ */
+ virtual bool OnHoverEvent(const HoverEvent& event) { return false; }
+
+ /**
+ * For use in derived classes.
* This is only called if the mouse wheel signal was not consumed.
* @param[in] event The mouse event.
* @return True if the event should be consumed.
// Signals
Dali::Actor::TouchSignalV2 mTouchedSignalV2;
+ Dali::Actor::HoverSignalV2 mHoveredSignalV2;
Dali::Actor::MouseWheelEventSignalV2 mMouseWheelEventSignalV2;
Dali::Actor::SetSizeSignalV2 mSetSizeSignalV2;
Dali::Actor::OnStageSignalV2 mOnStageSignalV2;
bool mLeaveRequired : 1; ///< Whether a touch event signal is emitted when the a touch leaves the actor's bounds
bool mKeyboardFocusable : 1; ///< Whether the actor should be focusable by keyboard navigation
bool mDerivedRequiresTouch : 1; ///< Whether the derived actor type requires touch event signals
+ bool mDerivedRequiresHover : 1; ///< Whether the derived actor type requires hover event signals
bool mDerivedRequiresMouseWheelEvent : 1; ///< Whether the derived actor type requires mouse wheel event signals
bool mOnStageSignalled : 1; ///< Set to true before OnStageConnection signal is emitted, and false before OnStageDisconnection
bool mInheritRotation : 1; ///< Cached: Whether the parent's rotation should be inherited.
mImpl( &extension )
{
mDerivedRequiresTouch = extension.RequiresTouchEvents();
+ mDerivedRequiresHover = extension.RequiresHoverEvents();
mDerivedRequiresMouseWheelEvent = extension.RequiresMouseWheelEvents();
}
}
/**
+ * @copydoc Internal::Actor::OnHoverEvent
+ */
+ virtual bool OnHoverEvent(const HoverEvent& event)
+ {
+ return mImpl->OnHoverEvent(event);
+ }
+
+ /**
* @copydoc Internal::Actor::OnKeyEvent
*/
virtual bool OnKeyEvent(const KeyEvent& event)
mSortFunction(Dali::Layer::ZValue),
mIsClipping(false),
mDepthTestDisabled(false),
- mTouchConsumed(false)
+ mTouchConsumed(false),
+ mHoverConsumed(false)
{
}
return mTouchConsumed;
}
+void Layer::SetHoverConsumed( bool consume )
+{
+ mHoverConsumed = consume;
+}
+
+bool Layer::IsHoverConsumed() const
+{
+ return mHoverConsumed;
+}
+
SceneGraph::Node* Layer::CreateNode() const
{
return SceneGraph::Layer::New();
bool IsTouchConsumed() const;
/**
+ * @copydoc Dali::Layer::SetHoverConsumed()
+ */
+ void SetHoverConsumed( bool consume );
+
+ /**
+ * @copydoc Dali::Layer::IsHoverConsumed()
+ */
+ bool IsHoverConsumed() const;
+
+ /**
* Helper function to get the scene object.
* This should only be called by Stage
* @return the scene object for the layer.
bool mIsClipping:1; ///< True when clipping is enabled
bool mDepthTestDisabled:1; ///< Whether depth test is disabled.
bool mTouchConsumed:1; ///< Whether we should consume touch (including gesture).
+ bool mHoverConsumed:1; ///< Whether we should consume hover.
static bool mFirstInstance;
static DefaultPropertyLookup* mDefaultLayerPropertyLookup; ///< Default properties
--- /dev/null
+/*
+ * Copyright (c) 2014 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/integration-api/debug.h>
+#include <dali/internal/event/actors/actor-impl.h>
+#include <dali/internal/event/events/actor-observer.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace
+{
+#if defined(DEBUG_ENABLED)
+Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_ACTOR_OBSERVER" );
+#endif // defined(DEBUG_ENABLED)
+}
+
+ActorObserver::ActorObserver::ActorObserver()
+: mActor ( NULL ),
+ mActorDisconnected(false)
+{
+ DALI_LOG_TRACE_METHOD( gLogFilter );
+}
+
+ActorObserver::ActorObserver::~ActorObserver()
+{
+ DALI_LOG_TRACE_METHOD( gLogFilter );
+ SetActor( NULL );
+}
+
+Actor* ActorObserver::ActorObserver::GetActor()
+{
+ return mActorDisconnected ? NULL : mActor;
+}
+
+void ActorObserver::ActorObserver::SetActor( Actor* actor )
+{
+ DALI_LOG_TRACE_METHOD( gLogFilter );
+
+ if ( mActor != actor )
+ {
+ ResetActor();
+
+ mActor = actor;
+
+ if ( mActor )
+ {
+ mActor->AddObserver( *this );
+ DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Start Observing: %p\n", mActor);
+ }
+ }
+
+ // Make sure this flag is unset (as we may have been disconnected if it's the same actor)
+ mActorDisconnected = false;
+}
+
+void ActorObserver::ActorObserver::ResetActor()
+{
+ if ( mActor )
+ {
+ DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Stop Observing: %p\n", mActor);
+ mActor->RemoveObserver( *this );
+ mActor = NULL;
+ mActorDisconnected = false;
+ }
+}
+
+void ActorObserver::ActorObserver::SceneObjectRemoved( ProxyObject& proxy )
+{
+ DALI_LOG_TRACE_METHOD( gLogFilter );
+
+ if ( mActor == &proxy )
+ {
+ // do not call proxy.RemoveObserver here, proxy is currently iterating through observers... you wouldnt want to upset proxy now would you?
+ mActorDisconnected = true;
+ }
+}
+
+void ActorObserver::ActorObserver::ProxyDestroyed(ProxyObject& proxy)
+{
+ DALI_LOG_TRACE_METHOD( gLogFilter );
+
+ if ( mActor == &proxy )
+ {
+ DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Stop Observing: %p\n", mActor);
+ mActor = NULL;
+ }
+}
+
+} // namespace Internal
+
+} // namespace Dali
+
--- /dev/null
+#ifndef __DALI_INTERNAL_ACTOR_OBSERVER_H__
+#define __DALI_INTERNAL_ACTOR_OBSERVER_H__
+
+/*
+ * Copyright (c) 2014 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/internal/event/common/proxy-object.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+class Actor;
+
+/**
+ * Stores an actor pointer and connects/disconnects to any required signals appropriately when set/unset.
+ */
+struct ActorObserver : public ProxyObject::Observer
+{
+public:
+
+ // Construction & Destruction
+
+ /**
+ * Constructor.
+ */
+ ActorObserver();
+
+ /**
+ * Non virtual destructor
+ */
+ ~ActorObserver();
+
+ // Methods
+
+ /**
+ * Return the stored Actor pointer.
+ * @return The Actor pointer.
+ */
+ Actor* GetActor();
+
+ /**
+ * Assignment operator.
+ * This disconnects the required signals from the currently set actor and connects to the required
+ * signals for the the actor specified (if set).
+ */
+ void SetActor( Actor* actor );
+
+ /**
+ * Resets the set actor and disconnects any connected signals.
+ */
+ void ResetActor();
+
+private:
+
+ // Undefined
+ ActorObserver( const ActorObserver& );
+ ActorObserver& operator=( const ActorObserver& );
+
+private:
+
+ /**
+ * This will never get called as we do not observe objects that have not been added to the scene.
+ * @param[in] proxy The proxy object.
+ * @see ProxyObject::Observer::SceneObjectAdded()
+ */
+ virtual void SceneObjectAdded(ProxyObject& proxy) { }
+
+ /**
+ * This will be called when the actor is removed from the stage, we should clear and stop
+ * observing it.
+ * @param[in] proxy The proxy object.
+ * @see ProxyObject::Observer::SceneObjectRemoved()
+ */
+ virtual void SceneObjectRemoved(ProxyObject& proxy);
+
+ /**
+ * This will be called when the actor is destroyed. We should clear the actor.
+ * No need to stop observing as the object is being destroyed anyway.
+ * @see ProxyObject::Observer::ProxyDestroyed()
+ */
+ virtual void ProxyDestroyed(ProxyObject& proxy);
+
+private:
+ Actor* mActor; ///< Raw pointer to an Actor.
+ bool mActorDisconnected; ///< Indicates whether the actor has been disconnected from the scene
+};
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_ACTOR_OBSERVER_H__
+
#include <dali/integration-api/events/key-event-integ.h>
#include <dali/integration-api/events/mouse-wheel-event-integ.h>
#include <dali/integration-api/events/touch-event-integ.h>
+#include <dali/integration-api/events/hover-event-integ.h>
#include <dali/integration-api/events/pinch-gesture-event.h>
#include <dali/integration-api/events/pan-gesture-event.h>
#include <dali/integration-api/events/tap-gesture-event.h>
EventProcessor::EventProcessor(Stage& stage, NotificationManager& /* notificationManager */, GestureEventProcessor& gestureEventProcessor)
: mTouchEventProcessor(stage),
+ mHoverEventProcessor(stage),
mGestureEventProcessor(gestureEventProcessor),
mKeyEventProcessor(stage),
mMouseWheelEventProcessor(stage),
break;
}
+ case Event::Hover:
+ {
+ typedef Integration::HoverEvent DerivedType;
+
+ // Reserve some memory inside the message queue
+ unsigned int* slot = mCurrentEventQueue->ReserveMessageSlot( sizeof( DerivedType ) );
+
+ // Construct message in the message queue memory; note that delete should not be called on the return value
+ new (slot) DerivedType( static_cast<const DerivedType&>(event) );
+
+ break;
+ }
+
case Event::Key:
{
typedef Integration::KeyEvent DerivedType;
break;
}
+ case Event::Hover:
+ {
+ mHoverEventProcessor.ProcessHoverEvent( static_cast<const Integration::HoverEvent&>(*event) );
+ break;
+ }
+
case Event::Key:
{
mKeyEventProcessor.ProcessKeyEvent( static_cast<const Integration::KeyEvent&>(*event) );
// INTERNAL INCLUDES
#include <dali/internal/event/events/touch-event-processor.h>
+#include <dali/internal/event/events/hover-event-processor.h>
#include <dali/internal/event/events/key-event-processor.h>
#include <dali/internal/event/events/mouse-wheel-event-processor.h>
#include <dali/internal/common/message-buffer.h>
private:
TouchEventProcessor mTouchEventProcessor; ///< Processes touch events.
+ HoverEventProcessor mHoverEventProcessor; ///< Processes hover events.
GestureEventProcessor& mGestureEventProcessor; ///< Processes gesture events.
KeyEventProcessor mKeyEventProcessor; ///< Processes key events.
MouseWheelEventProcessor mMouseWheelEventProcessor; ///< Processes mouse wheel events.
--- /dev/null
+/*
+ * Copyright (c) 2014 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/event/events/hover-event-processor.h>
+
+#if defined(DEBUG_ENABLED)
+#include <sstream>
+#endif
+
+// INTERNAL INCLUDES
+#include <dali/public-api/actors/renderable-actor.h>
+#include <dali/public-api/math/vector2.h>
+#include <dali/integration-api/debug.h>
+#include <dali/integration-api/events/hover-event-integ.h>
+#include <dali/internal/event/actors/actor-impl.h>
+#include <dali/internal/event/actors/layer-impl.h>
+#include <dali/internal/event/common/stage-impl.h>
+#include <dali/internal/event/events/hit-test-algorithm-impl.h>
+#include <dali/internal/event/events/multi-point-event-util.h>
+#include <dali/internal/event/render-tasks/render-task-impl.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace
+{
+
+#if defined(DEBUG_ENABLED)
+Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_HOVER_PROCESSOR" );
+
+const char * TOUCH_POINT_STATE[TouchPoint::Last] =
+{
+ "Started",
+ "Finished",
+ "Motion",
+ "Leave",
+ "Stationary",
+ "Interrupted",
+};
+
+#endif // defined(DEBUG_ENABLED)
+
+/**
+ * Recursively deliver events to the actor and its parents, until the event is consumed or the stage is reached.
+ */
+Dali::Actor EmitHoverSignals( Dali::Actor actor, const HoverEvent& event )
+{
+ Dali::Actor consumedActor;
+
+ if ( actor )
+ {
+ Dali::Actor oldParent( actor.GetParent() );
+
+ Actor& actorImpl( GetImplementation(actor) );
+
+ bool consumed( false );
+
+ // Only emit the signal if the actor's hover signal has connections (or derived actor implementation requires hover).
+ if ( actorImpl.GetHoverRequired() )
+ {
+ consumed = actorImpl.EmitHoverEventSignal( event );
+ }
+
+ if ( consumed )
+ {
+ // One of this actor's listeners has consumed the event so set this actor as the consumed actor.
+ consumedActor = Dali::Actor( &actorImpl );
+ }
+ else
+ {
+ // The actor may have been removed/reparented during the signal callbacks.
+ Dali::Actor parent = actor.GetParent();
+
+ if ( parent &&
+ (parent == oldParent) )
+ {
+ // One of the actor's parents may consumed the event and they should be set as the consumed actor.
+ consumedActor = EmitHoverSignals( parent, event );
+ }
+ }
+ }
+
+ return consumedActor;
+}
+
+/**
+ * Changes the state of the primary point to leave and emits the hover signals
+ */
+Dali::Actor EmitHoverSignals( Actor* actor, RenderTask& renderTask, const HoverEvent& originalEvent, TouchPoint::State state )
+{
+ HoverEvent hoverEvent( originalEvent );
+
+ DALI_ASSERT_DEBUG( NULL != actor && "NULL actor pointer" );
+ if( actor )
+ {
+ TouchPoint& primaryPoint = hoverEvent.points[0];
+
+ actor->ScreenToLocal( renderTask, primaryPoint.local.x, primaryPoint.local.y, primaryPoint.screen.x, primaryPoint.screen.y );
+
+ primaryPoint.hitActor = Dali::Actor(actor);
+ primaryPoint.state = state;
+ }
+
+ return EmitHoverSignals( Dali::Actor(actor), hoverEvent );
+}
+
+/**
+ * Used in the hit-test algorithm to check whether the actor is hoverable.
+ */
+struct ActorHoverableCheck : public HitTestAlgorithm::HitTestInterface
+{
+ bool IsActorHittable( Actor* actor )
+ {
+ return actor->GetHoverRequired() && // Does the Application or derived actor type require a hover event?
+ actor->IsHittable(); // Is actor sensitive, visible and on the scene?
+ }
+
+ bool DescendActorHierarchy( Actor* actor )
+ {
+ return actor->IsVisible() && // Actor is visible, if not visible then none of its children are visible.
+ actor->IsSensitive(); // Actor is sensitive, if insensitive none of its children should be hittable either.
+ }
+
+ bool DoesLayerConsumeHit( Layer* layer )
+ {
+ return layer->IsHoverConsumed();
+ }
+};
+
+} // unnamed namespace
+
+HoverEventProcessor::HoverEventProcessor( Stage& stage )
+: mStage( stage ),
+ mLastPrimaryHitActor(),
+ mLastConsumedActor(),
+ mHoverStartConsumedActor(),
+ mLastRenderTask()
+{
+ DALI_LOG_TRACE_METHOD( gLogFilter );
+}
+
+HoverEventProcessor::~HoverEventProcessor()
+{
+ DALI_LOG_TRACE_METHOD( gLogFilter );
+}
+
+void HoverEventProcessor::ProcessHoverEvent( const Integration::HoverEvent& event )
+{
+ DALI_LOG_TRACE_METHOD( gLogFilter );
+
+ DALI_ASSERT_ALWAYS( !event.points.empty() && "Empty HoverEvent sent from Integration\n" );
+
+ Stage& stage = mStage;
+
+ PRINT_HIERARCHY(gLogFilter);
+
+ // Copy so we can add the results of a hit-test.
+ HoverEvent hoverEvent( event.time );
+
+ // 1) Check if it is an interrupted event - we should inform our last primary hit actor about this
+ // and emit the stage signal as well.
+
+ if ( event.points[0].state == TouchPoint::Interrupted )
+ {
+ Dali::Actor consumingActor;
+ hoverEvent.points.push_back(event.points[0]);
+
+ Actor* lastPrimaryHitActor( mLastPrimaryHitActor.GetActor() );
+ if ( lastPrimaryHitActor )
+ {
+ Dali::Actor lastPrimaryHitActorHandle( lastPrimaryHitActor );
+ hoverEvent.points[0].hitActor = lastPrimaryHitActorHandle;
+ consumingActor = EmitHoverSignals( lastPrimaryHitActorHandle, hoverEvent );
+ }
+
+ // If the last consumed actor was different to the primary hit actor then inform it as well (if it has not already been informed).
+ Actor* lastConsumedActor( mLastConsumedActor.GetActor() );
+ if ( lastConsumedActor &&
+ lastConsumedActor != lastPrimaryHitActor &&
+ lastConsumedActor != consumingActor )
+ {
+ Dali::Actor lastConsumedActorHandle( lastConsumedActor );
+ hoverEvent.points[0].hitActor = lastConsumedActorHandle;
+ EmitHoverSignals( lastConsumedActorHandle, hoverEvent );
+ }
+
+ // Tell the hover-start consuming actor as well, if required
+ Actor* hoverStartConsumedActor( mHoverStartConsumedActor.GetActor() );
+ if ( hoverStartConsumedActor &&
+ hoverStartConsumedActor != lastPrimaryHitActor &&
+ hoverStartConsumedActor != lastConsumedActor &&
+ hoverStartConsumedActor != consumingActor )
+ {
+ Dali::Actor hoverStartConsumedActorHandle( hoverStartConsumedActor );
+ hoverEvent.points[0].hitActor = hoverStartConsumedActorHandle;
+ EmitHoverSignals( hoverStartConsumedActorHandle, hoverEvent );
+ }
+
+ mLastPrimaryHitActor.SetActor( NULL );
+ mLastConsumedActor.SetActor( NULL );
+ mHoverStartConsumedActor.SetActor( NULL );
+ mLastRenderTask.Reset();
+
+ hoverEvent.points[0].hitActor = NULL;
+
+ return; // No need for hit testing
+ }
+
+ // 2) Hit Testing.
+
+ DALI_LOG_INFO( gLogFilter, Debug::Concise, "\n" );
+ DALI_LOG_INFO( gLogFilter, Debug::General, "Point(s): %d\n", event.GetPointCount() );
+
+ Dali::RenderTask currentRenderTask;
+
+ for ( TouchPointContainerConstIterator iter = event.points.begin(), beginIter = event.points.begin(), endIter = event.points.end(); iter != endIter; ++iter )
+ {
+ HitTestAlgorithm::Results hitTestResults;
+ ActorHoverableCheck actorHoverableCheck;
+ HitTestAlgorithm::HitTest( stage, iter->screen, hitTestResults, actorHoverableCheck );
+
+ TouchPoint newPoint( iter->deviceId, iter->state, iter->screen.x, iter->screen.y );
+ newPoint.hitActor = hitTestResults.actor;
+ newPoint.local = hitTestResults.actorCoordinates;
+
+ hoverEvent.points.push_back( newPoint );
+
+ DALI_LOG_INFO( gLogFilter, Debug::General, " State(%s), Screen(%.0f, %.0f), HitActor(%p, %s), Local(%.2f, %.2f)\n",
+ TOUCH_POINT_STATE[iter->state], iter->screen.x, iter->screen.y,
+ ( hitTestResults.actor ? (void*)&hitTestResults.actor.GetBaseObject() : NULL ),
+ ( hitTestResults.actor ? hitTestResults.actor.GetName().c_str() : "" ),
+ hitTestResults.actorCoordinates.x, hitTestResults.actorCoordinates.y );
+
+ // Only set the currentRenderTask for the primary hit actor.
+ if ( iter == beginIter && hitTestResults.renderTask )
+ {
+ currentRenderTask = hitTestResults.renderTask;
+ }
+ }
+
+ // 3) Recursively deliver events to the actor and its parents, until the event is consumed or the stage is reached.
+
+ // Emit the touch signal
+ Dali::Actor consumedActor;
+ if ( currentRenderTask )
+ {
+ consumedActor = EmitHoverSignals( hoverEvent.points[0].hitActor, hoverEvent );
+ }
+
+ TouchPoint& primaryPoint = hoverEvent.points[0];
+ Dali::Actor primaryHitActor = primaryPoint.hitActor;
+ TouchPoint::State primaryPointState = primaryPoint.state;
+
+ DALI_LOG_INFO( gLogFilter, Debug::Concise, "PrimaryHitActor: (%p) %s\n", primaryPoint.hitActor ? (void*)&primaryPoint.hitActor.GetBaseObject() : NULL, primaryPoint.hitActor ? primaryPoint.hitActor.GetName().c_str() : "" );
+ DALI_LOG_INFO( gLogFilter, Debug::Concise, "ConsumedActor: (%p) %s\n", consumedActor ? (void*)&consumedActor.GetBaseObject() : NULL, consumedActor ? consumedActor.GetName().c_str() : "" );
+
+ if ( ( primaryPointState == TouchPoint::Started ) &&
+ ( hoverEvent.GetPointCount() == 1 ) &&
+ ( consumedActor && consumedActor.OnStage() ) )
+ {
+ mHoverStartConsumedActor.SetActor( &GetImplementation( consumedActor ) );
+ }
+
+ // 4) Check if the last primary hit actor requires a leave event and if it was different to the current primary
+ // hit actor. Also process the last consumed actor in the same manner.
+
+ Actor* lastPrimaryHitActor( mLastPrimaryHitActor.GetActor() );
+ Actor* lastConsumedActor( mLastConsumedActor.GetActor() );
+ if( (primaryPointState == TouchPoint::Motion) || (primaryPointState == TouchPoint::Finished) || (primaryPointState == TouchPoint::Stationary) )
+ {
+ if ( mLastRenderTask )
+ {
+ Dali::Actor leaveEventConsumer;
+ RenderTask& lastRenderTaskImpl( GetImplementation( mLastRenderTask ) );
+
+ if( lastPrimaryHitActor &&
+ lastPrimaryHitActor != primaryHitActor &&
+ lastPrimaryHitActor != consumedActor )
+ {
+ if( lastPrimaryHitActor->IsHittable() && IsActuallySensitive( lastPrimaryHitActor ) )
+ {
+ if ( lastPrimaryHitActor->GetLeaveRequired() )
+ {
+ DALI_LOG_INFO( gLogFilter, Debug::Concise, "LeaveActor(Hit): (%p) %s\n", (void*)lastPrimaryHitActor, lastPrimaryHitActor->GetName().c_str() );
+ leaveEventConsumer = EmitHoverSignals( mLastPrimaryHitActor.GetActor(), lastRenderTaskImpl, hoverEvent, TouchPoint::Leave );
+ }
+ }
+ else
+ {
+ // At this point mLastPrimaryHitActor was touchable and sensitive in the previous touch event process but is not in the current one.
+ // An interrupted event is send to allow some actors to go back to their original state (i.e. Button controls)
+ DALI_LOG_INFO( gLogFilter, Debug::Concise, "InterruptedActor(Hit): (%p) %s\n", (void*)lastPrimaryHitActor, lastPrimaryHitActor->GetName().c_str() );
+ leaveEventConsumer = EmitHoverSignals( mLastPrimaryHitActor.GetActor(), lastRenderTaskImpl, hoverEvent, TouchPoint::Interrupted );
+ }
+ }
+
+ // Check if the motion event has been consumed by another actor's listener. In this case, the previously
+ // consumed actor's listeners may need to be informed (through a leave event).
+ // Further checks here to ensure we do not signal the same actor twice for the same event.
+ if ( lastConsumedActor &&
+ lastConsumedActor != consumedActor &&
+ lastConsumedActor != lastPrimaryHitActor &&
+ lastConsumedActor != primaryHitActor &&
+ lastConsumedActor != leaveEventConsumer )
+ {
+ if( lastConsumedActor->IsHittable() && IsActuallySensitive( lastConsumedActor ) )
+ {
+ if( lastConsumedActor->GetLeaveRequired() )
+ {
+ DALI_LOG_INFO( gLogFilter, Debug::Concise, "LeaveActor(Consume): (%p) %s\n", (void*)lastConsumedActor, lastConsumedActor->GetName().c_str() );
+ EmitHoverSignals( lastConsumedActor, lastRenderTaskImpl, hoverEvent, TouchPoint::Leave );
+ }
+ }
+ else
+ {
+ // At this point mLastConsumedActor was touchable and sensitive in the previous touch event process but is not in the current one.
+ // An interrupted event is send to allow some actors to go back to their original state (i.e. Button controls)
+ DALI_LOG_INFO( gLogFilter, Debug::Concise, "InterruptedActor(Consume): (%p) %s\n", (void*)lastConsumedActor, lastConsumedActor->GetName().c_str() );
+ EmitHoverSignals( mLastConsumedActor.GetActor(), lastRenderTaskImpl, hoverEvent, TouchPoint::Interrupted );
+ }
+ }
+ }
+ }
+
+ // 5) If our primary point is an Finished event, then the primary point (in multi-touch) will change next
+ // time so set our last primary actor to NULL. Do the same to the last consumed actor as well.
+
+ if ( primaryPointState == TouchPoint::Finished )
+ {
+ mLastPrimaryHitActor.SetActor( NULL );
+ mLastConsumedActor.SetActor( NULL );
+ mLastRenderTask.Reset();
+ }
+ else
+ {
+ // The primaryHitActor may have been removed from the stage so ensure it is still on the stage before setting members.
+ if ( primaryHitActor && primaryHitActor.OnStage() )
+ {
+ mLastPrimaryHitActor.SetActor( &GetImplementation( primaryHitActor ) );
+
+ // Only observe the consumed actor if we have a primaryHitActor (check if it is still on stage).
+ if ( consumedActor && consumedActor.OnStage() )
+ {
+ mLastConsumedActor.SetActor( &GetImplementation( consumedActor ) );
+ }
+ else
+ {
+ mLastConsumedActor.SetActor( NULL );
+ }
+
+ mLastRenderTask = currentRenderTask;
+ }
+ else
+ {
+ mLastPrimaryHitActor.SetActor( NULL );
+ mLastConsumedActor.SetActor( NULL );
+ mLastRenderTask.Reset();
+ }
+ }
+
+ // 6) Emit an interrupted event to the hover-started actor if it hasn't consumed the Finished.
+
+ if ( hoverEvent.GetPointCount() == 1 ) // Only want the first hover started
+ {
+ switch ( primaryPointState )
+ {
+ case TouchPoint::Finished:
+ {
+ Actor* hoverStartConsumedActor( mHoverStartConsumedActor.GetActor() );
+ if ( hoverStartConsumedActor &&
+ hoverStartConsumedActor != consumedActor &&
+ hoverStartConsumedActor != lastPrimaryHitActor &&
+ hoverStartConsumedActor != lastConsumedActor )
+ {
+ Dali::Actor hoverStartConsumedActorHandle( hoverStartConsumedActor );
+ hoverEvent.points[0].hitActor = hoverStartConsumedActorHandle;
+ hoverEvent.points[0].state = TouchPoint::Interrupted;
+ EmitHoverSignals( hoverStartConsumedActorHandle, hoverEvent );
+
+ // Restore hover-event to original state
+ hoverEvent.points[0].hitActor = primaryHitActor;
+ hoverEvent.points[0].state = primaryPointState;
+ }
+
+ mHoverStartConsumedActor.SetActor( NULL );
+ }
+ // No break, Fallthrough
+
+ case TouchPoint::Started:
+ case TouchPoint::Motion:
+ case TouchPoint::Leave:
+ case TouchPoint::Stationary:
+ case TouchPoint::Interrupted:
+ case TouchPoint::Last:
+ {
+ // Ignore
+ break;
+ }
+ }
+ }
+}
+
+} // namespace Internal
+
+} // namespace Dali
--- /dev/null
+#ifndef __DALI_INTERNAL_HOVER_EVENT_PROCESSOR_H__
+#define __DALI_INTERNAL_HOVER_EVENT_PROCESSOR_H__
+
+/*
+ * Copyright (c) 2014 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/render-tasks/render-task.h>
+#include <dali/internal/event/events/actor-observer.h>
+
+namespace Dali
+{
+
+class Actor;
+struct Vector2;
+struct Vector4;
+
+namespace Integration
+{
+struct HoverEvent;
+}
+
+namespace Internal
+{
+
+class ActorObserver;
+class Stage;
+
+/**
+ * <h3>Multi-Hover Event Processing:</h3>
+ *
+ * The HoverEventProcessor processes hover events and emits the Hovered signal on the hit actor (and
+ * its parents).
+ *
+ * - Hit Testing & Hover Event Delivery are described in Dali::Actor.
+ */
+class HoverEventProcessor
+{
+public:
+
+ /**
+ * Create an event processor.
+ * @param[in] stage The stage.
+ */
+ HoverEventProcessor( Stage& stage );
+
+ /**
+ * Non-virtual destructor; HoverEventProcessor is not a base class
+ */
+ ~HoverEventProcessor();
+
+ /**
+ * This function is called by the event processor whenever a hover event occurs.
+ * @param[in] event The hover event that has occurred.
+ */
+ void ProcessHoverEvent( const Integration::HoverEvent& event );
+
+private:
+
+ // Undefined
+ HoverEventProcessor(const HoverEventProcessor&);
+
+ // Undefined
+ HoverEventProcessor& operator=(const HoverEventProcessor& rhs);
+
+ Stage& mStage; ///< Used to deliver touch events
+ ActorObserver mLastPrimaryHitActor; ///< Stores the last primary point hit actor
+ ActorObserver mLastConsumedActor; ///< Stores the last consumed actor
+ ActorObserver mHoverStartConsumedActor; ///< Stores the hover-start consumed actor
+ Dali::RenderTask mLastRenderTask; ///< The RenderTask used for the last hit actor
+};
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_HOVER_EVENT_PROCESSOR_H__
--- /dev/null
+/*
+ * Copyright (c) 2014 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#if defined(DEBUG_ENABLED)
+#include <sstream>
+#endif
+
+// CLASS HEADER
+#include <dali/internal/event/common/stage-impl.h>
+#include <dali/internal/event/events/multi-point-event-util.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+#if defined(DEBUG_ENABLED)
+
+static bool HIERARCHY_GEOMETRY(false);
+static bool HIERARCHY_SENSITIVITY(false);
+static bool HIERARCHY_TOUCH_REQUIRED(false);
+static bool HIERARCHY_HOVER_REQUIRED(false);
+static bool HIERARCHY_HITTABLE(false);
+
+static const Debug::LogLevel HIERARCHY_DEBUG_LOG_LEVEL( Debug::Verbose );
+
+void PrintChildren( Debug::Filter* logFilter, Dali::Actor actor, int level )
+{
+ std::ostringstream output;
+
+ for ( int t = 0; t < level; ++t )
+ {
+ output << " | ";
+ }
+
+ output << actor.GetName() << "(" << actor.GetTypeName() << ", " << actor.GetObjectPtr() << ")";
+
+ if ( HIERARCHY_GEOMETRY )
+ {
+ output << " Pos: " << actor.GetCurrentWorldPosition() << " Size: " << actor.GetCurrentSize() << " Scale: " << actor.GetCurrentWorldScale();
+ }
+
+ if ( HIERARCHY_SENSITIVITY )
+ {
+ output << " Sensitivity: " << ( IsActuallySensitive( &GetImplementation( actor ) ) ? "True " : "False " );
+ }
+
+ if ( HIERARCHY_TOUCH_REQUIRED )
+ {
+ output << " TouchRequired: " << ( GetImplementation(actor).GetTouchRequired() ? "True " : "False " );
+ }
+
+ if ( HIERARCHY_HOVER_REQUIRED )
+ {
+ output << " HoverRequired: " << ( GetImplementation(actor).GetHoverRequired() ? "True " : "False " );
+ }
+
+ if ( HIERARCHY_HITTABLE )
+ {
+ output << " Hittable: " << ( GetImplementation(actor).IsHittable() ? "True " : "False " );
+ }
+
+ output << std::endl;
+
+ if( logFilter )
+ {
+ DALI_LOG_INFO( logFilter, HIERARCHY_DEBUG_LOG_LEVEL, output.str().c_str() );
+ }
+
+ ++level;
+ unsigned int numChildren=actor.GetChildCount();
+ for ( unsigned int i=0; i<numChildren; ++i )
+ {
+ PrintChildren( logFilter, actor.GetChildAt(i), level );
+ }
+ --level;
+}
+
+void PrintHierarchy( Debug::Filter* logFilter )
+{
+ if ( logFilter && logFilter->IsEnabledFor( HIERARCHY_DEBUG_LOG_LEVEL ) )
+ {
+ PrintChildren( logFilter, Dali::Stage().GetCurrent().GetRootLayer(), 0 );
+ }
+}
+
+#endif // defined(DEBUG_ENABLED)
+
+bool IsActuallySensitive( Actor* actor )
+{
+ bool sensitive = true;
+
+ while ( actor && sensitive )
+ {
+ sensitive = actor->IsSensitive();
+ actor = actor->GetParent();
+ }
+
+ return sensitive;
+}
+
+} // namespace Internal
+
+} // namespace Dali
+
--- /dev/null
+#ifndef __DALI_INTERNAL_MULTI_POINT_EVENT_UTIL_H__
+#define __DALI_INTERNAL_MULTI_POINT_EVENT_UTIL_H__
+
+/*
+ * Copyright (c) 2014 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/integration-api/debug.h>
+#include <dali/internal/event/actors/actor-impl.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+#if defined(DEBUG_ENABLED)
+
+/**
+ * Prints out all the children of the given actor when debug is enabled.
+ *
+ * @param[in] actor The actor whose children to print.
+ * @param[in] level The number of " | " to put in front of the children.
+ */
+void PrintChildren( Debug::Filter* logFilter, Dali::Actor actor, int level );
+
+/**
+ * Prints the entire hierarchy of the scene.
+ */
+void PrintHierarchy( Debug::Filter* logFilter );
+
+#define PRINT_HIERARCHY(f) PrintHierarchy(f)
+
+#else // defined(DEBUG_ENABLED)
+
+#define PRINT_HIERARCHY(f)
+
+#endif // defined(DEBUG_ENABLED)
+
+/**
+ * In the hit test algorithm above we do not descend actor tree if it is insensitive, so here, we
+ * should also check if any of the actor's parents has become insensitive since we last processed
+ * it.
+ */
+bool IsActuallySensitive( Actor* actor );
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_MULTI_POINT_EVENT_UTIL_H__
+
#include <dali/internal/event/actors/layer-impl.h>
#include <dali/internal/event/common/stage-impl.h>
#include <dali/internal/event/events/hit-test-algorithm-impl.h>
+#include <dali/internal/event/events/multi-point-event-util.h>
#include <dali/internal/event/render-tasks/render-task-impl.h>
namespace Dali
namespace
{
-bool IsActuallySensitive( Actor* actor );
-
#if defined(DEBUG_ENABLED)
Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_TOUCH_PROCESSOR" );
"Interrupted",
};
-static const Debug::LogLevel HIERARCHY_DEBUG_LOG_LEVEL( Debug::Verbose );
-
-static bool HIERARCHY_GEOMETRY( false );
-static bool HIERARCHY_SENSITIVITY( false );
-static bool HIERARCHY_TOUCH_REQUIRED( false );
-static bool HIERARCHY_HITTABLE( false );
-
-/**
- * Prints out all the children of the given actor when debug is enabled.
- *
- * @param[in] actor The actor whose children to print.
- * @param[in] level The number of " | " to put in front of the children.
- */
-void PrintChildren( Dali::Actor actor, int level )
-{
- std::ostringstream output;
-
- for ( int t = 0; t < level; ++t )
- {
- output << " | ";
- }
-
- output << actor.GetName() << "(" << actor.GetTypeName() << ", " << actor.GetObjectPtr() << ")";
-
- if ( HIERARCHY_GEOMETRY )
- {
- output << " Pos: " << actor.GetCurrentWorldPosition() << " Size: " << actor.GetCurrentSize() << " Scale: " << actor.GetCurrentWorldScale();
- }
-
- if ( HIERARCHY_SENSITIVITY )
- {
- output << " Sensitivity: " << ( IsActuallySensitive( &GetImplementation( actor ) ) ? "True " : "False " );
- }
-
- if ( HIERARCHY_TOUCH_REQUIRED )
- {
- output << " TouchRequired: " << ( GetImplementation(actor).GetTouchRequired() ? "True " : "False " );
- }
-
- if ( HIERARCHY_HITTABLE )
- {
- output << " Hittable: " << ( GetImplementation(actor).IsHittable() ? "True " : "False " );
- }
-
- output << std::endl;
-
- DALI_LOG_INFO( gLogFilter, HIERARCHY_DEBUG_LOG_LEVEL, output.str().c_str() );
-
- ++level;
- unsigned int numChildren=actor.GetChildCount();
- for ( unsigned int i=0; i<numChildren; ++i )
- {
- PrintChildren( actor.GetChildAt(i), level );
- }
- --level;
-}
-
-/**
- * Prints the entire hierarchy of the scene.
- */
-void PrintHierarchy()
-{
- if ( gLogFilter->IsEnabledFor( HIERARCHY_DEBUG_LOG_LEVEL ) )
- {
- PrintChildren( Dali::Stage().GetCurrent().GetRootLayer(), 0 );
- }
-}
-
-#define PRINT_HIERARCHY PrintHierarchy()
-
-#else // defined(DEBUG_ENABLED)
-
-#define PRINT_HIERARCHY
-
#endif // defined(DEBUG_ENABLED)
/**
return EmitTouchSignals( Dali::Actor(actor), touchEvent );
}
-/**
- * In the hit test algorithm above we do not descend actor tree if it is insensitive, so here, we
- * should also check if any of the actor's parents has become insensitive since we last processed
- * it.
- */
-bool IsActuallySensitive( Actor* actor )
-{
- bool sensitive = true;
-
- while ( actor && sensitive )
- {
- sensitive = actor->IsSensitive();
- actor = actor->GetParent();
- }
-
- return sensitive;
-}
-
} // unnamed namespace
TouchEventProcessor::TouchEventProcessor( Stage& stage )
Stage& stage = mStage;
- PRINT_HIERARCHY;
+ PRINT_HIERARCHY(gLogFilter);
// Copy so we can add the results of a hit-test.
TouchEvent touchEvent( event.time );
}
}
-TouchEventProcessor::ActorObserver::ActorObserver()
-: mActor ( NULL ),
- mActorDisconnected(false)
-{
- DALI_LOG_TRACE_METHOD( gLogFilter );
-}
-
-TouchEventProcessor::ActorObserver::~ActorObserver()
-{
- DALI_LOG_TRACE_METHOD( gLogFilter );
- SetActor( NULL );
-}
-
-Actor* TouchEventProcessor::ActorObserver::GetActor()
-{
- return mActorDisconnected ? NULL : mActor;
-}
-
-void TouchEventProcessor::ActorObserver::SetActor( Actor* actor )
-{
- DALI_LOG_TRACE_METHOD( gLogFilter );
-
- if ( mActor != actor )
- {
- ResetActor();
-
- mActor = actor;
-
- if ( mActor )
- {
- mActor->AddObserver( *this );
- DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Start Observing: %p\n", mActor);
- }
- }
-
- // Make sure this flag is unset (as we may have been disconnected if it's the same actor)
- mActorDisconnected = false;
-}
-
-void TouchEventProcessor::ActorObserver::ResetActor()
-{
- if ( mActor )
- {
- DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Stop Observing: %p\n", mActor);
- mActor->RemoveObserver( *this );
- mActor = NULL;
- mActorDisconnected = false;
- }
-}
-
-void TouchEventProcessor::ActorObserver::SceneObjectRemoved( ProxyObject& proxy )
-{
- DALI_LOG_TRACE_METHOD( gLogFilter );
-
- if ( mActor == &proxy )
- {
- // do not call proxy.RemoveObserver here, proxy is currently iterating through observers... you wouldnt want to upset proxy now would you?
- mActorDisconnected = true;
- }
-}
-
-void TouchEventProcessor::ActorObserver::ProxyDestroyed(ProxyObject& proxy)
-{
- DALI_LOG_TRACE_METHOD( gLogFilter );
-
- if ( mActor == &proxy )
- {
- DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Stop Observing: %p\n", mActor);
- mActor = NULL;
- }
-}
-
} // namespace Internal
} // namespace Dali
// INTERNAL INCLUDES
#include <dali/public-api/render-tasks/render-task.h>
-#include <dali/internal/event/common/proxy-object.h>
+#include <dali/internal/event/events/actor-observer.h>
namespace Dali
{
class Actor;
class Stage;
+class ActorObserver;
/**
* <h3>Multi-Touch Event Processing:</h3>
private:
- /**
- * Stores an actor pointer and connects/disconnects to any required signals appropriately when set/unset.
- */
- struct ActorObserver : public ProxyObject::Observer
- {
- public:
-
- // Construction & Destruction
-
- /**
- * Constructor.
- */
- ActorObserver();
-
- /**
- * Non virtual destructor
- */
- ~ActorObserver();
-
- // Methods
-
- /**
- * Return the stored Actor pointer.
- * @return The Actor pointer.
- */
- Actor* GetActor();
-
- /**
- * Assignment operator.
- * This disconnects the required signals from the currently set actor and connects to the required
- * signals for the the actor specified (if set).
- */
- void SetActor( Actor* actor );
-
- /**
- * Resets the set actor and disconnects any connected signals.
- */
- void ResetActor();
-
- private:
-
- // Undefined
- ActorObserver( const ActorObserver& );
- ActorObserver& operator=( const ActorObserver& );
-
- private:
-
- /**
- * This will never get called as we do not observe objects that have not been added to the scene.
- * @param[in] proxy The proxy object.
- * @see ProxyObject::Observer::SceneObjectAdded()
- */
- virtual void SceneObjectAdded(ProxyObject& proxy) { }
-
- /**
- * This will be called when the actor is removed from the stage, we should clear and stop
- * observing it.
- * @param[in] proxy The proxy object.
- * @see ProxyObject::Observer::SceneObjectRemoved()
- */
- virtual void SceneObjectRemoved(ProxyObject& proxy);
-
- /**
- * This will be called when the actor is destroyed. We should clear the actor.
- * No need to stop observing as the object is being destroyed anyway.
- * @see ProxyObject::Observer::ProxyDestroyed()
- */
- virtual void ProxyDestroyed(ProxyObject& proxy);
-
- private:
- Actor* mActor; ///< Raw pointer to an Actor.
- bool mActorDisconnected; ///< Indicates whether the actor has been disconnected from the scene
- };
-
Stage& mStage; ///< Used to deliver touch events
ActorObserver mLastPrimaryHitActor; ///< Stores the last primary point hit actor
ActorObserver mLastConsumedActor; ///< Stores the last consumed actor
$(internal_src_dir)/event/effects/shader-effect-impl.cpp \
$(internal_src_dir)/event/effects/shader-factory.cpp \
$(internal_src_dir)/event/events/actor-gesture-data.cpp \
+ $(internal_src_dir)/event/events/actor-observer.cpp \
$(internal_src_dir)/event/events/event-processor.cpp \
$(internal_src_dir)/event/events/key-event-processor.cpp \
$(internal_src_dir)/event/events/gesture-detector-impl.cpp \
$(internal_src_dir)/event/events/gesture-event-processor.cpp \
$(internal_src_dir)/event/events/gesture-processor.cpp \
$(internal_src_dir)/event/events/hit-test-algorithm-impl.cpp \
+ $(internal_src_dir)/event/events/hover-event-processor.cpp \
$(internal_src_dir)/event/events/long-press-gesture-detector-impl.cpp \
$(internal_src_dir)/event/events/long-press-gesture-processor.cpp \
$(internal_src_dir)/event/events/mouse-wheel-event-processor.cpp \
+ $(internal_src_dir)/event/events/multi-point-event-util.cpp \
$(internal_src_dir)/event/events/pan-gesture-detector-impl.cpp \
$(internal_src_dir)/event/events/pan-gesture-processor.cpp \
$(internal_src_dir)/event/events/pinch-gesture-detector-impl.cpp \
{
const char* const Actor::SIGNAL_TOUCHED = "touched";
+const char* const Actor::SIGNAL_HOVERED = "hovered";
const char* const Actor::SIGNAL_MOUSE_WHEEL_EVENT = "mouse-wheel-event";
const char* const Actor::SIGNAL_SET_SIZE = "set-size";
const char* const Actor::SIGNAL_ON_STAGE = "on-stage";
return GetImplementation(*this).TouchedSignal();
}
+Actor::HoverSignalV2& Actor::HoveredSignal()
+{
+ return GetImplementation(*this).HoveredSignal();
+}
+
Actor::MouseWheelEventSignalV2& Actor::MouseWheelEventSignal()
{
return GetImplementation(*this).MouseWheelEventSignal();
struct Radian;
struct KeyEvent;
struct TouchEvent;
+struct HoverEvent;
struct MouseWheelEvent;
struct Vector2;
struct Vector3;
*
* <h3>Multi-Touch Events:</h3>
*
- * Touch events are received via signals; see Actor::TouchedSignal() for more details.
+ * Touch or hover events are received via signals; see Actor::TouchedSignal() and Actor::HoveredSignal() for more details.
*
* <i>Hit Testing Rules Summary:</i>
*
- * - An actor is only hittable if the actor's touch signal has a connection.
+ * - An actor is only hittable if the actor's touch or hover signal has a connection.
* - An actor is only hittable when it is between the camera's near and far planes.
* - If an actor is made insensitive, then the actor and its children are not hittable; see IsSensitive()
* - If an actor's visibility flag is unset, then none of its children are hittable either; see IsVisible()
* // Depth-first traversal within current layer, visiting parent first
*
* // Check whether current actor should be hit-tested
- * IF ( TOUCH-SIGNAL-NOT-EMPTY &&
+ * IF ( ( TOUCH-SIGNAL-NOT-EMPTY || HOVER-SIGNAL-NOT-EMPTY ) &&
* ACTOR-HAS-NON-ZERO-SIZE &&
* ACTOR-WORLD-COLOR-IS-NOT-TRANSPARENT )
* {
* also be considered a Stencil Actor.
* Non-renderable actors can be hit regardless of whether a stencil actor is hit or not.
*
- * <i>Touch Event Delivery:</i>
+ * <i>Touch or hover Event Delivery:</i>
*
* - Delivery
- * - The hit actor's touch signal is emitted first; if it is not consumed by any of the listeners,
- * the parent's touch signal is emitted, and so on.
+ * - The hit actor's touch or hover signal is emitted first; if it is not consumed by any of the listeners,
+ * the parent's touch or hover signal is emitted, and so on.
* - The following pseudocode shows the delivery mechanism:
* @code
* EMIT-TOUCH-SIGNAL( ACTOR )
* }
* }
* }
+ *
+ * EMIT-HOVER-SIGNAL( ACTOR )
+ * {
+ * IF ( HOVER-SIGNAL-NOT-EMPTY )
+ * {
+ * // Only do the emission if hover signal of actor has connections.
+ * CONSUMED = HOVERED-SIGNAL( HOVER-EVENT )
+ * }
+ *
+ * IF ( NOT-CONSUMED )
+ * {
+ * // If event is not consumed then deliver it to the parent unless we reach the root actor
+ * IF ( ACTOR-PARENT )
+ * {
+ * EMIT-HOVER-SIGNAL( ACTOR-PARENT )
+ * }
+ * }
+ * }
* @endcode
* - If there are several touch points, then the delivery is only to the first touch point's hit
- * actor (and its parents). There will be NO touch signal delivery for the hit actors of the
+ * actor (and its parents). There will be NO touch or hover signal delivery for the hit actors of the
* other touch points.
* - The local coordinates are from the top-left (0.0f, 0.0f, 0.5f) of the hit actor.
*
* - Leave State
* - A "Leave" state is set when the first point exits the bounds of the previous first point's
* hit actor (primary hit actor).
- * - When this happens, the last primary hit actor's touch signal is emitted with a "Leave" state
+ * - When this happens, the last primary hit actor's touch or hover signal is emitted with a "Leave" state
* (only if it requires leave signals); see SetLeaveRequired().
*
* - Interrupted State
- * - If a system event occurs which interrupts the touch processing, then the last primary hit
- * actor's touch signals are emitted with an "Interrupted" state.
- * - If the last primary hit actor, or one of its parents, is no longer touchable, then its
- * touch signals are also emitted with an "Interrupted" state.
+ * - If a system event occurs which interrupts the touch or hover processing, then the last primary hit
+ * actor's touch or hover signals are emitted with an "Interrupted" state.
+ * - If the last primary hit actor, or one of its parents, is no longer touchable or hoverable, then its
+ * touch or hover signals are also emitted with an "Interrupted" state.
* - If the consumed actor on touch-down is not the same as the consumed actor on touch-up, then
* touch signals are also emitted from the touch-down actor with an "Interrupted" state.
+ * - If the consumed actor on hover-start is not the same as the consumed actor on hover-finished, then
+ * hover signals are also emitted from the hover-started actor with an "Interrupted" state.
* <h3>Key Events:</h3>
*
* Key events are received by an actor once set to grab key events, only one actor can be set as focused.
// Typedefs
typedef SignalV2< bool (Actor, const TouchEvent&)> TouchSignalV2; ///< Touch signal type
+ typedef SignalV2< bool (Actor, const HoverEvent&)> HoverSignalV2; ///< Hover signal type
typedef SignalV2< bool (Actor, const MouseWheelEvent&) > MouseWheelEventSignalV2;///< Mousewheel signal type
typedef SignalV2< void (Actor, const Vector3&) > SetSizeSignalV2; ///< SetSize signal type
typedef SignalV2< void (Actor) > OnStageSignalV2; ///< Stage connection signal type
/// @name Signals
/** @{ */
static const char* const SIGNAL_TOUCHED; ///< name "touched", @see TouchedSignal()
+ static const char* const SIGNAL_HOVERED; ///< name "hovered", @see HoveredSignal()
static const char* const SIGNAL_MOUSE_WHEEL_EVENT; ///< name "mouse-wheel-event", @see MouseWheelEventSignal()
static const char* const SIGNAL_SET_SIZE; ///< name "set-size", @see SetSizeSignal()
static const char* const SIGNAL_ON_STAGE; ///< name "on-stage", @see OnStageSignal()
// Input Handling
/**
- * @brief Sets whether an actor should emit touch event signals; @see SignalTouched().
+ * @brief Sets whether an actor should emit touch or hover signals; see SignalTouch() and SignalHover().
*
- * An actor is sensitive by default, which means that as soon as an application connects to the SignalTouched(),
- * the touch event signal will be emitted.
+ * An actor is sensitive by default, which means that as soon as an application connects to the SignalTouch(),
+ * the touch event signal will be emitted, and as soon as an application connects to the SignalHover(), the
+ * hover event signal will be emitted.
*
- * If the application wishes to temporarily disable the touch event signal emission, then they can do so by calling:
+ * If the application wishes to temporarily disable the touch or hover event signal emission, then they can do so by calling:
* @code
* actor.SetSensitive(false);
* @endcode
*
- * Then, to re-enable the touch event signal emission, the application should call:
+ * Then, to re-enable the touch or hover event signal emission, the application should call:
* @code
* actor.SetSensitive(true);
* @endcode
*
- * @see SignalTouched().
+ * @see @see SignalTouch() and SignalHover().
* @note If an actor's sensitivity is set to false, then it's children will not be hittable either.
* This is regardless of the individual sensitivity values of the children i.e. an actor will only be
* hittable if all of its parents have sensitivity set to true.
* @pre The Actor has been initialized.
- * @param[in] sensitive true to enable emission of the touch event signals, false otherwise.
+ * @param[in] sensitive true to enable emission of the touch or hover event signals, false otherwise.
*/
void SetSensitive(bool sensitive);
/**
- * @brief Query whether an actor emits touch event signals.
+ * @brief Query whether an actor emits touch or hover event signals.
*
* @note If an actor is not sensitive, then it's children will not be hittable either.
* This is regardless of the individual sensitivity values of the children i.e. an actor will only be
* hittable if all of its parents have sensitivity set to true.
* @pre The Actor has been initialized.
- * @return true, if emission of touch event signals is enabled, false otherwise.
+ * @return true, if emission of touch or hover event signals is enabled, false otherwise.
*/
bool IsSensitive() const;
bool ScreenToLocal(float& localX, float& localY, float screenX, float screenY) const;
/**
- * @brief Sets whether the actor should receive a notification when touch motion events leave
+ * @brief Sets whether the actor should receive a notification when touch or hover motion events leave
* the boundary of the actor.
*
* @note By default, this is set to false as most actors do not require this.
- * @note Need to connect to the SignalTouch to actually receive this event.
+ * @note Need to connect to the SignalTouch or SignalHover to actually receive this event.
*
* @pre The Actor has been initialized.
* @param[in] required Should be set to true if a Leave event is required
void SetLeaveRequired(bool required);
/**
- * @brief This returns whether the actor requires touch events whenever touch motion events leave
+ * @brief This returns whether the actor requires touch or hover events whenever touch or hover motion events leave
* the boundary of the actor.
*
* @pre The Actor has been initialized.
TouchSignalV2& TouchedSignal();
/**
+ * @brief This signal is emitted when hover input is received.
+ *
+ * A callback of the following type may be connected:
+ * @code
+ * bool YourCallbackName(Actor actor, const HoverEvent& event);
+ * @endcode
+ * The return value of True, indicates that the hover event should be consumed.
+ * Otherwise the signal will be emitted on the next sensitive parent of the actor.
+ * @pre The Actor has been initialized.
+ * @return The signal to connect to.
+ */
+ HoverSignalV2& HoveredSignal();
+
+ /**
* @brief This signal is emitted when mouse wheel event is received.
*
* A callback of the following type may be connected:
CustomActorImpl::CustomActorImpl(bool requiresTouchEvents)
: mOwner(NULL),
mRequiresTouchEvents(requiresTouchEvents),
+ mRequiresHoverEvents(false),
mRequiresMouseWheelEvents(false)
{
}
return mRequiresTouchEvents;
}
+bool CustomActorImpl::RequiresHoverEvents() const
+{
+ return mRequiresHoverEvents;
+}
+
+void CustomActorImpl::SetRequiresHoverEvents(bool requiresHoverEvents)
+{
+ mRequiresHoverEvents = requiresHoverEvents;
+}
+
bool CustomActorImpl::RequiresMouseWheelEvents() const
{
return mRequiresMouseWheelEvents;
class CustomActorImpl;
struct KeyEvent;
struct TouchEvent;
+struct HoverEvent;
struct MouseWheelEvent;
struct Vector3;
virtual bool OnTouchEvent(const TouchEvent& event) = 0;
/**
+ * @brief Called after a hover-event is received by the owning actor.
+ *
+ * @note This must be enabled during construction; see CustomActorImpl::SetRequiresHoverEvents(bool)
+ * @param[in] event The hover event.
+ * @return True if the event should be consumed.
+ */
+ virtual bool OnHoverEvent(const HoverEvent& event) = 0;
+
+ /**
* @brief Called after a key-event is received by the actor that has had its focus set.
*
* @param[in] event the Key Event
CustomActorImpl(bool requiresTouchEvents);
/**
+ * @brief Set whether the custom actor requires hover events.
+ * @param[in] requiresHoverEvents True if the OnHoverEvent() callback is required.
+ */
+ void SetRequiresHoverEvents(bool requiresHoverEvents);
+
+ /**
* @brief Set whether the custom actor requires mouse wheel events.
* @param[in] requiresMouseWheelEvents True if the OnMouseWheelEvent() callback is required.
*/
/**
* @brief Called when ownership of the CustomActorImpl is passed to a CustomActor.
+ * @return True if the OnHoverEvent() callback is required.
+ */
+ bool RequiresHoverEvents() const;
+
+ /**
+ * @brief Called when ownership of the CustomActorImpl is passed to a CustomActor.
* @return True if the OnMouseWheelEvent() callback is required.
*/
bool RequiresMouseWheelEvents() const;
Internal::CustomActor* mOwner; ///< Internal owner of this custom actor implementation
bool mRequiresTouchEvents; ///< Whether the OnTouchEvent() callback is required
+ bool mRequiresHoverEvents; ///< Whether the OnHoverEvent() callback is required
bool mRequiresMouseWheelEvents; ///< Whether the OnMouseWheelEvent() callback is required
};
return GetImplementation( *this ).IsTouchConsumed();
}
+void Layer::SetHoverConsumed( bool consume )
+{
+ GetImplementation( *this ).SetHoverConsumed( consume );
+}
+
+bool Layer::IsHoverConsumed() const
+{
+ return GetImplementation( *this ).IsHoverConsumed();
+}
+
Layer::Layer(Internal::Layer* internal)
: Actor(internal)
{
*/
bool IsTouchConsumed() const;
+ /**
+ * @brief This allows the user to specify whether this layer should consume hover.
+ *
+ * If set, any layers behind this layer will not be hit-test.
+ *
+ * @param[in] consume Whether the layer should consume hover.
+ */
+ void SetHoverConsumed( bool consume );
+
+ /**
+ * @brief Retrieves whether the layer consumes hover.
+ *
+ * @return true if consuming hover, false otherwise.
+ */
+ bool IsHoverConsumed() const;
+
public: // Not intended for application developers
/**
#include <dali/public-api/events/gesture-detector.h>
#include <dali/public-api/events/gesture.h>
#include <dali/public-api/events/hit-test-algorithm.h>
+#include <dali/public-api/events/hover-event.h>
#include <dali/public-api/events/key-event.h>
#include <dali/public-api/events/long-press-gesture-detector.h>
#include <dali/public-api/events/long-press-gesture.h>
--- /dev/null
+/*
+ * Copyright (c) 2014 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/public-api/events/hover-event.h>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-common.h>
+
+namespace Dali
+{
+
+HoverEvent::HoverEvent()
+: time(0)
+{
+}
+
+HoverEvent::HoverEvent(unsigned long time)
+: time(time)
+{
+}
+
+HoverEvent::~HoverEvent()
+{
+}
+
+unsigned int HoverEvent::GetPointCount() const
+{
+ return points.size();
+}
+
+const TouchPoint& HoverEvent::GetPoint(unsigned int point) const
+{
+ DALI_ASSERT_ALWAYS( point < points.size() && "No point at index" );
+ return points[point];
+}
+
+} // namespace Dali
--- /dev/null
+#ifndef __DALI_HOVER_EVENT_H__
+#define __DALI_HOVER_EVENT_H__
+
+/*
+ * Copyright (c) 2014 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/vector-wrapper.h>
+#include <dali/public-api/common/dali-common.h>
+#include <dali/public-api/events/touch-point.h>
+
+namespace Dali DALI_IMPORT_API
+{
+
+/**
+ * @brief Hover events are a collection of touch points at a specific moment in time.
+ *
+ * When a multi-touch event occurs, each touch point represents the points that are currently being
+ * hovered or the points where a hover has stopped.
+ */
+struct DALI_IMPORT_API HoverEvent
+{
+ // Construction & Destruction
+
+ /**
+ * @brief Default constructor
+ */
+ HoverEvent();
+
+ /**
+ * @brief Constructor
+ * @param[in] time The time the event occurred
+ */
+ HoverEvent(unsigned long time);
+
+ /**
+ * @brief Destructor
+ */
+ ~HoverEvent();
+
+ // Data
+
+ /**
+ * @brief This is a container of points for this hover event.
+ *
+ * The first point in the set is always the
+ * primary touch point (i.e. the first point touched in a multi-touch event).
+ */
+ TouchPointContainer points;
+
+ /**
+ * @brief The time (in ms) that the hover event occurred.
+ */
+ unsigned long time;
+
+ // Convenience Methods
+
+ /**
+ * @brief Returns the total number of points in this HoverEvent.
+ *
+ * @return Total number of Points.
+ */
+ unsigned int GetPointCount() const;
+
+ /**
+ * @brief Returns a touch point at the index requested.
+ *
+ * The first point in the set is always the primary
+ * touch point (i.e. the first point touched in a multi-touch event).
+ * @note "point" should be less than the value returned by GetPointCount().
+ * If out of range, then program asserts.
+ * @param[in] point The index of the required Point.
+ * @return Point requested
+ */
+ const TouchPoint& GetPoint(unsigned int point) const;
+};
+
+} // namespace Dali
+
+#endif // __DALI_HOVER_EVENT_H__
namespace Dali DALI_IMPORT_API
{
-typedef std::vector<TouchPoint> TouchPointContainer; ///< Container of touch points.
-typedef TouchPointContainer::iterator TouchPointContainerIterator; ///< Iterator for Dali::TouchPointContainer
-typedef TouchPointContainer::const_iterator TouchPointContainerConstIterator; ///< Const iterator for Dali::TouchPointContainer
-
/**
* @brief Touch events are a collection of touch points at a specific moment in time.
*
*/
enum State
{
- Down, /**< Screen touched */
- Up, /**< Touch stopped */
- Motion, /**< Finger dragged */
- Leave, /**< Leave the boundary of an actor */
- Stationary, /**< No change from last event. Useful when a multi-touch event occurs where
- all points are sent but indicates that this particular point has not changed
- since the last time */
- Interrupted, /**< A system event has occurred which has interrupted the touch event sequence. */
- Last /**< Number of states. */
+ Started, /**< Touch or hover started */
+ Finished, /**< Touch or hover finished */
+ Down = Started, /**< Screen touched */
+ Up = Finished, /**< Touch stopped */
+ Motion, /**< Finger dragged or hovered */
+ Leave, /**< Leave the boundary of an actor */
+ Stationary, /**< No change from last event. Useful when a multi-point event occurs where
+ all points are sent but indicates that this particular point has not changed
+ since the last time */
+ Interrupted, /**< A system event has occurred which has interrupted the touch or hover event sequence. */
+ Last /**< Number of states. */
};
// Construction & Destruction
Vector2 screen;
};
+typedef std::vector<TouchPoint> TouchPointContainer; ///< Container of touch points.
+typedef TouchPointContainer::iterator TouchPointContainerIterator; ///< Iterator for Dali::TouchPointContainer
+typedef TouchPointContainer::const_iterator TouchPointContainerConstIterator; ///< Const iterator for Dali::TouchPointContainer
+
} // namespace Dali
#endif // __DALI_TOUCH_POINT_H__
$(public_api_src_dir)/events/gesture.cpp \
$(public_api_src_dir)/events/gesture-detector.cpp \
$(public_api_src_dir)/events/hit-test-algorithm.cpp \
+ $(public_api_src_dir)/events/hover-event.cpp \
$(public_api_src_dir)/events/key-event.cpp \
$(public_api_src_dir)/events/long-press-gesture.cpp \
$(public_api_src_dir)/events/long-press-gesture-detector.cpp \
$(public_api_src_dir)/events/gesture.h \
$(public_api_src_dir)/events/gesture-detector.h \
$(public_api_src_dir)/events/hit-test-algorithm.h \
+ $(public_api_src_dir)/events/hover-event.h \
$(public_api_src_dir)/events/key-event.h \
$(public_api_src_dir)/events/long-press-gesture.h \
$(public_api_src_dir)/events/long-press-gesture-detector.h \