Fixed crash for stage touched signal callback in JavaScript
[platform/core/uifw/dali-toolkit.git] / plugins / dali-script-v8 / src / events / event-object-generator.cpp
1 /*
2  * Copyright (c) 2015 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 // CLASS HEADER
19 #include "event-object-generator.h"
20
21 // INTERNAL INCLUDES
22 #include <v8-utils.h>
23 #include <actors/actor-wrapper.h>
24 #include <object/property-value-wrapper.h>
25
26 namespace Dali
27 {
28
29 namespace V8Plugin
30 {
31
32 namespace
33 {
34
35 struct PointState
36 {
37   TouchPoint::State state;
38   const char* name;
39 };
40
41 const PointState PointStateLookup[]=
42 {
43     { TouchPoint::Down,         "down"        },       /**< Screen touched */
44     { TouchPoint::Up,           "up"          },       /**< Touch stopped */
45     { TouchPoint::Motion,       "motion"      },       /**< Touch stopped */
46     { TouchPoint::Leave,        "leave"       },       /**< Touch stopped */
47     { TouchPoint::Stationary,   "stationary"  },       /**< Touch stopped */
48     { TouchPoint::Interrupted,  "interrupt"   },       /**< Touch stopped */
49     { TouchPoint::Started,      "started"     },       /**< Touch or hover started */
50     { TouchPoint::Finished,     "finished"    },       /**< Touch or hover finished */
51 };
52
53 const unsigned int PointStateLookupCount = sizeof(PointStateLookup)/sizeof(PointStateLookup[0]);
54
55 struct GestureState
56 {
57   Gesture::State state;
58   const char* name;
59 };
60
61 const GestureState GestureStateLookup[]=
62 {
63     { Gesture::Clear,      "clear"        },       /**< No state associated */
64     { Gesture::Started,    "started"      },       /**< Gesture started */
65     { Gesture::Continuing, "continuing"   },       /**< Gesture continuing */
66     { Gesture::Finished,   "finished"     },       /**< Gesture finished */
67     { Gesture::Cancelled,  "cancelled"    },       /**< Gesture cancelled */
68     { Gesture::Possible,   "possible"     },       /**< Gesture is possible */
69 };
70
71 const unsigned int GestureStateLookupCount = sizeof(GestureStateLookup)/sizeof(GestureStateLookup[0]);
72
73 const char* GetTouchPointStateName( TouchPoint::State state )
74 {
75   // could use the enum as index, but dali-core may change, so for now just do a lookup
76   for( unsigned int i = 0; i < PointStateLookupCount; i++ )
77   {
78     if( PointStateLookup[i].state == state )
79     {
80       return PointStateLookup[i].name;
81     }
82   }
83   return "error point state not found";
84 }
85
86 const char* GetGestureStateName( Gesture::State state )
87 {
88   // could use the enum as index, but dali-core may change, so for now just do a lookup
89   for( unsigned int i = 0; i < GestureStateLookupCount; i++ )
90   {
91     if( GestureStateLookup[i].state == state )
92     {
93       return GestureStateLookup[i].name;
94     }
95   }
96   return "error gesture state not found";
97 }
98
99 // create a point object, x,y
100 v8::Local<v8::Object> CreateTouchPoint( v8::Isolate* isolate, const TouchPoint& touchPoint )
101 {
102   /*
103    * touch point object
104    *
105    *   { "deviceId",  int }  Each touch point has a unique device ID
106    *   { "state",   string } touch state ="Down,Up,Motion,Leave,Stationary, Interrupted }
107    *   { "hitActor", actor } actor that was hit ( wrapped dali object)
108    *   { "local",  {x,y} } co-ordinates of top left of hit actor
109    *   { "screen", {x,y} } co-ordinates of top left of hit actor
110    */
111   v8::EscapableHandleScope handleScope( isolate );
112
113   v8::Local<v8::Object> pointObject = v8::Object::New( isolate );
114
115   // set device id
116   pointObject->Set( v8::String::NewFromUtf8( isolate, "deviceId"), v8::Integer::New( isolate, touchPoint.deviceId ));
117
118   // set state
119   pointObject->Set( v8::String::NewFromUtf8( isolate, "state"), v8::String::NewFromUtf8( isolate, GetTouchPointStateName(touchPoint.state)));
120
121   if(touchPoint.hitActor)
122   {
123     // set the hit actor
124     pointObject->Set( v8::String::NewFromUtf8( isolate, "hitActor"), ActorWrapper::WrapActor(isolate, touchPoint.hitActor ));
125   }
126
127   // Think about changing these Vector 2 from wrapped objects to JavaScript objects...
128
129   // Set the local co-ordinates
130   v8::Local<v8::Object> localPointObject = v8::Object::New( isolate );
131   localPointObject->Set( v8::String::NewFromUtf8( isolate, "x"),v8::Integer::New( isolate, touchPoint.local.x) );
132   localPointObject->Set( v8::String::NewFromUtf8( isolate, "y"),v8::Integer::New( isolate, touchPoint.local.y) );
133   pointObject->Set( v8::String::NewFromUtf8( isolate, "local"),  localPointObject);
134
135
136   // set the screen co-ordinates
137   v8::Local<v8::Object> screenPointObject = v8::Object::New( isolate );
138   screenPointObject->Set( v8::String::NewFromUtf8( isolate, "x"),v8::Integer::New( isolate, touchPoint.screen.x) );
139   screenPointObject->Set( v8::String::NewFromUtf8( isolate, "y"),v8::Integer::New( isolate, touchPoint.screen.y) );
140   pointObject->Set( v8::String::NewFromUtf8( isolate, "screen"), screenPointObject );
141
142
143   return handleScope.Escape( pointObject );
144 }
145
146 } // un-named namespace
147
148
149 v8::Handle<v8::Object> EventObjectGenerator::CreateTouchEvent( v8::Isolate* isolate, const TouchEvent& touchEvent)
150 {
151   // we are creating a touch event object that looks like this
152   //
153   //  event.pointCount = points touched
154   //  event.time       = The time (in ms) that the touch event occurred.
155   //  event.point[]    = array of TouchPoints
156   //
157   // A TouchPoint =
158   //   { "deviceId",  int }  Each touch point has a unique device ID
159   //   { "state",   string } touch state ="Down,Up,Motion,Leave,Stationary, Interrupted }
160   //   { "sourceActor", actor }  the actor that is emitting the callback (the actor that is hit maybe a child of it)
161   //   { "hitActor", actor } actor that was hit
162   //   { "local",  {x,y} } co-ordinates of top left of hit actor
163   //   { "screen", {x,y} } co-ordinates of top left of hit actor
164   //
165
166   v8::EscapableHandleScope handleScope( isolate );
167
168   v8::Local<v8::Object> touchObject = v8::Object::New( isolate );
169
170   // Set the pointCount
171   touchObject->Set( v8::String::NewFromUtf8( isolate, "pointCount" ), v8::Integer::New( isolate, touchEvent.GetPointCount() ) );
172
173   // Set the time
174   touchObject->Set( v8::String::NewFromUtf8( isolate, "time" ), v8::Number::New( isolate, touchEvent.time ) );
175
176   // Set the emitting actor
177   // touchObject->Set( v8::String::NewFromUtf8( isolate, "sourceActor" ), ActorWrapper::WrapActor(isolate, emittingActor));
178
179   // Create the array of touch points
180   v8::Local < v8::Array > pointArrayObject = v8::Array::New( isolate, touchEvent.GetPointCount() );
181   for( unsigned int i = 0 ; i < touchEvent.GetPointCount() ; ++i )
182   {
183     v8::Local < v8::Object > pointObject = CreateTouchPoint( isolate, touchEvent.points[i] );
184     pointArrayObject->Set( v8::Number::New( isolate, i ), pointObject  );
185   }
186
187   // set the array
188   touchObject->Set( v8::String::NewFromUtf8( isolate, "points" ), pointArrayObject );
189
190   return handleScope.Escape( touchObject );
191 }
192
193 v8::Handle<v8::Object> EventObjectGenerator::CreateHoverEvent( v8::Isolate* isolate, const HoverEvent& hoverEvent)
194 {
195   // we are creating a hover event object that looks like this
196   //
197   //  event.pointCount = points hovered
198   //  event.time       = The time (in ms) that the hover event occurred.
199   //  event.point[]    = array of TouchPoints
200   //
201   // A TouchPoint =
202   //   { "deviceId",  int }  Each touch point has a unique device ID
203   //   { "state",   string } touch state ="Down,Up,Motion,Leave,Stationary, Interrupted }
204   //   { "sourceActor", actor }  the actor that is emitting the callback (the actor that is hit maybe a child of it)
205   //   { "hitActor", actor } actor that was hit
206   //   { "local",  {x,y} } co-ordinates of top left of hit actor
207   //   { "screen", {x,y} } co-ordinates of top left of hit actor
208   //
209
210   v8::EscapableHandleScope handleScope( isolate );
211
212   v8::Local<v8::Object> hoverObject = v8::Object::New( isolate );
213
214   // Set the pointCount
215   hoverObject->Set( v8::String::NewFromUtf8( isolate, "pointCount" ), v8::Integer::New( isolate, hoverEvent.GetPointCount() ) );
216
217   // Set the time
218   hoverObject->Set( v8::String::NewFromUtf8( isolate, "time" ), v8::Number::New( isolate, hoverEvent.time ) );
219
220   // Set the emitting actor
221   // hoverObject->Set( v8::String::NewFromUtf8( isolate, "sourceActor" ), ActorWrapper::WrapActor(isolate, emittingActor));
222
223   // Create the array of touch points
224   v8::Local < v8::Array > pointArrayObject = v8::Array::New( isolate, hoverEvent.GetPointCount() );
225   for( unsigned int i = 0 ; i < hoverEvent.GetPointCount() ; ++i )
226   {
227     v8::Local < v8::Object > pointObject = CreateTouchPoint( isolate, hoverEvent.points[i] );
228     pointArrayObject->Set( v8::Number::New( isolate, i ), pointObject  );
229   }
230
231   // set the array
232   hoverObject->Set( v8::String::NewFromUtf8( isolate, "points" ), pointArrayObject );
233
234   return handleScope.Escape( hoverObject );
235 }
236
237 v8::Handle<v8::Object> EventObjectGenerator::CreateWheelEvent( v8::Isolate* isolate, const WheelEvent& wheelEvent)
238 {
239   //  we are creating a wheel event object that looks like this
240   //
241   //  event.type = "mouseWheel" or "customWheel" type of the wheel event
242   //  event.direction = "vertical" or "horizontal" direction the wheel is being rolled
243   //  event.shiftPressed       = boolean, shift key is held
244   //  event.ctrlPressed        = boolean, ctrl key is held
245   //  event.altPressed     = boolean, alt key is held
246   //  event.keyModifiers = bitmask of keys pressed
247   //  event.point {x,y}    = The co-ordinates of the mouse cursor relative to the top-left of the screen when the wheel is being rolled.
248   //  event.rolled          = offset of wheel rolling, positive = rolling down or clockwise, negative = rolling up or counter-clockwise
249   //  event.timestamp    = The time (in ms) that the touch event occurred
250
251   v8::EscapableHandleScope handleScope( isolate );
252
253   v8::Local<v8::Object> wheelObject = v8::Object::New( isolate );
254
255   // Set the type
256   std::string type = wheelEvent.type ? "mouseWheel" : "customWheel";
257   wheelObject->Set( v8::String::NewFromUtf8( isolate, "type" ), v8::String::NewFromUtf8( isolate, type.c_str() ) );
258
259   // Set the direction
260   std::string direction = wheelEvent.direction ? "vertical" : "horizontal";
261   wheelObject->Set( v8::String::NewFromUtf8( isolate, "direction" ), v8::String::NewFromUtf8( isolate, direction.c_str() ) );
262
263   // set shift / ctrl/ alt keys
264   wheelObject->Set( v8::String::NewFromUtf8( isolate, "shiftPressed" ), v8::Boolean::New( isolate, wheelEvent.IsShiftModifier()) );
265   wheelObject->Set( v8::String::NewFromUtf8( isolate, "ctrlPressed" ),  v8::Boolean::New( isolate, wheelEvent.IsCtrlModifier()) );
266   wheelObject->Set( v8::String::NewFromUtf8( isolate, "altPressed" ),   v8::Boolean::New( isolate, wheelEvent.IsAltModifier()) );
267
268   // set keyModifiers
269   wheelObject->Set( v8::String::NewFromUtf8( isolate, "keyModifiers" ),  v8::Integer::New( isolate, wheelEvent.modifiers) );
270
271   // set Point
272   v8::Local<v8::Object> wheelPointObject = v8::Object::New( isolate );
273   wheelPointObject->Set( v8::String::NewFromUtf8( isolate, "x"),v8::Integer::New( isolate, wheelEvent.point.x ) );
274   wheelPointObject->Set( v8::String::NewFromUtf8( isolate, "y"),v8::Integer::New( isolate, wheelEvent.point.y ) );
275   wheelObject->Set( v8::String::NewFromUtf8( isolate, "point"), wheelPointObject );
276
277   // set rolledAmout
278   wheelObject->Set( v8::String::NewFromUtf8( isolate, "rolled" ),  v8::Integer::New( isolate, wheelEvent.z) );
279
280   // set timestamp
281   wheelObject->Set( v8::String::NewFromUtf8( isolate, "timestamp" ),  v8::Integer::New( isolate, wheelEvent.timeStamp) );
282
283   return handleScope.Escape( wheelObject );
284
285 }
286
287 v8::Handle<v8::Object> EventObjectGenerator::CreateKeyEvent( v8::Isolate* isolate, const KeyEvent& keyEvent)
288 {
289   // keyCode
290   // keyModifier
291   // event.keyCode       = key code
292   // event.key           = key presssed
293   // event.keyDescription = key description, e.g. BackSpace
294   // event.state = "down" or "up" key state
295   // event.shiftPressed  = boolean, shift key is held
296   // event.ctrlPressed   = boolean, ctrl key is held
297   // event.altPressed    = boolean, alt key is held
298   // event.keyModifiers  = key modifiers
299   // event.timestamp     = Time stamp
300
301   v8::EscapableHandleScope handleScope( isolate );
302
303   v8::Local<v8::Object> keyObject = v8::Object::New( isolate );
304
305   // Set the direction
306   std::string state ("up");
307   if ( keyEvent.state == KeyEvent::Down)
308   {
309     state = "down";
310   }
311
312   keyObject->Set( v8::String::NewFromUtf8( isolate, "state" ), v8::String::NewFromUtf8( isolate, state.c_str() ) );
313
314   // set keyCode
315    keyObject->Set( v8::String::NewFromUtf8( isolate, "keyCode" ),  v8::Integer::New( isolate, keyEvent.keyCode) );
316
317   // set keyModifiers
318   keyObject->Set( v8::String::NewFromUtf8( isolate, "keyModifier" ),  v8::Integer::New( isolate, keyEvent.keyModifier) );
319
320   // set Key pressed name
321   keyObject->Set( v8::String::NewFromUtf8( isolate, "keyDescription" ),  v8::String::NewFromUtf8( isolate, keyEvent.keyPressedName.c_str() )  );
322
323   // set Key pressed
324   keyObject->Set( v8::String::NewFromUtf8( isolate, "key" ),  v8::String::NewFromUtf8( isolate, keyEvent.keyPressed.c_str() )  );
325
326   // set time stamp
327   keyObject->Set( v8::String::NewFromUtf8( isolate, "timestamp" ),  v8::Integer::New( isolate, keyEvent.time) );
328
329   // set shift / ctrl/ alt keys
330   keyObject->Set( v8::String::NewFromUtf8( isolate, "shiftPressed" ), v8::Boolean::New( isolate, keyEvent.IsShiftModifier()) );
331   keyObject->Set( v8::String::NewFromUtf8( isolate, "ctrlPressed" ),  v8::Boolean::New( isolate, keyEvent.IsCtrlModifier()) );
332   keyObject->Set( v8::String::NewFromUtf8( isolate, "altPressed" ),   v8::Boolean::New( isolate, keyEvent.IsAltModifier()) );
333
334   return handleScope.Escape( keyObject );
335
336 }
337
338 v8::Handle<v8::Object> EventObjectGenerator::CreatePanGesture( v8::Isolate* isolate, const PanGesture& panGesture)
339 {
340   // gesture.numberOfTouches     = total number of fingers touching the screen
341   // gesture.state               = pan state {Clear, Started, Continuing, Finished, Cancelled, Possible}
342   // gesture.time                = Time stamp
343   // gesture.velocity            = pan velocity in actor coordinates
344   // gesture.displacement        = pan displacement in actor coordinates
345   // gesture.position            = pan position in actor coordinates
346   // gesture.screenVelocity      = pan velocity in screen coordinates
347   // gesture.screenDisplacement  = pan displacement in screen coordinates
348   // gesture.screenPosition      = pan position in screen coordinates
349
350   v8::EscapableHandleScope handleScope( isolate );
351
352   v8::Local<v8::Object> panObject = v8::Object::New( isolate );
353
354   // Set the numberOfTouches
355   panObject->Set( v8::String::NewFromUtf8( isolate, "numberOfTouches" ), v8::Integer::New( isolate, panGesture.numberOfTouches ) );
356
357   // Set the state
358   panObject->Set( v8::String::NewFromUtf8( isolate, "state"), v8::String::NewFromUtf8( isolate, GetGestureStateName(panGesture.state)));
359
360   // Set the time
361   panObject->Set( v8::String::NewFromUtf8( isolate, "time" ), v8::Number::New( isolate, panGesture.time ) );
362
363   // Set the local velocity
364   v8::Local<v8::Object> velocityObject = v8::Object::New( isolate );
365   velocityObject->Set( v8::String::NewFromUtf8( isolate, "x"),v8::Number::New( isolate, panGesture.velocity.x) );
366   velocityObject->Set( v8::String::NewFromUtf8( isolate, "y"),v8::Number::New( isolate, panGesture.velocity.y) );
367   panObject->Set( v8::String::NewFromUtf8( isolate, "velocity"),  velocityObject);
368
369   // Set the local displacement
370   v8::Local<v8::Object> displacementObject = v8::Object::New( isolate );
371   displacementObject->Set( v8::String::NewFromUtf8( isolate, "x"),v8::Number::New( isolate, panGesture.displacement.x) );
372   displacementObject->Set( v8::String::NewFromUtf8( isolate, "y"),v8::Number::New( isolate, panGesture.displacement.y) );
373   panObject->Set( v8::String::NewFromUtf8( isolate, "displacement"),  displacementObject);
374
375   // Set the local position
376   v8::Local<v8::Object> positionObject = v8::Object::New( isolate );
377   positionObject->Set( v8::String::NewFromUtf8( isolate, "x"),v8::Number::New( isolate, panGesture.position.x) );
378   positionObject->Set( v8::String::NewFromUtf8( isolate, "y"),v8::Number::New( isolate, panGesture.position.y) );
379   panObject->Set( v8::String::NewFromUtf8( isolate, "position"),  positionObject);
380
381   // Set the screen velocity
382   v8::Local<v8::Object> screenVelocityObject = v8::Object::New( isolate );
383   screenVelocityObject->Set( v8::String::NewFromUtf8( isolate, "x"),v8::Number::New( isolate, panGesture.screenVelocity.x) );
384   screenVelocityObject->Set( v8::String::NewFromUtf8( isolate, "y"),v8::Number::New( isolate, panGesture.screenVelocity.y) );
385   panObject->Set( v8::String::NewFromUtf8( isolate, "screenVelocity"),  screenVelocityObject);
386
387   // Set the screen displacement
388   v8::Local<v8::Object> screenDisplacementObject = v8::Object::New( isolate );
389   screenDisplacementObject->Set( v8::String::NewFromUtf8( isolate, "x"),v8::Number::New( isolate, panGesture.screenDisplacement.x) );
390   screenDisplacementObject->Set( v8::String::NewFromUtf8( isolate, "y"),v8::Number::New( isolate, panGesture.screenDisplacement.y) );
391   panObject->Set( v8::String::NewFromUtf8( isolate, "screenDisplacement"),  screenDisplacementObject);
392
393   // Set the screen position
394   v8::Local<v8::Object> screenPositionObject = v8::Object::New( isolate );
395   screenPositionObject->Set( v8::String::NewFromUtf8( isolate, "x"),v8::Number::New( isolate, panGesture.screenPosition.x) );
396   screenPositionObject->Set( v8::String::NewFromUtf8( isolate, "y"),v8::Number::New( isolate, panGesture.screenPosition.y) );
397   panObject->Set( v8::String::NewFromUtf8( isolate, "screenPosition"),  screenPositionObject);
398
399   return handleScope.Escape( panObject );
400
401 }
402
403
404
405 } // V8Plugin
406
407 } // namespace Dali