Merge "fix issue in negative line spacing with key arrow down" into devel/master
[platform/core/uifw/dali-toolkit.git] / automated-tests / src / dali-toolkit / utc-Dali-KeyInputFocusManager.cpp
1 /*
2  * Copyright (c) 2022 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 #include <dali-toolkit-test-suite-utils.h>
19 #include <dali-toolkit/dali-toolkit.h>
20 #include <dali-toolkit/devel-api/controls/control-devel.h>
21 #include <dali-toolkit/devel-api/focus-manager/keyinput-focus-manager.h>
22 #include <dali/devel-api/common/stage-devel.h>
23 #include <dali/integration-api/events/key-event-integ.h>
24 #include <stdlib.h>
25 #include <iostream>
26
27 #include "dummy-control.h"
28
29 using namespace Dali;
30 using namespace Toolkit;
31
32 namespace
33 {
34 /**
35  * Callback class for KeyInputFocusChanged signal.
36  */
37 class KeyInputFocusChangedCallback : public Dali::ConnectionTracker
38 {
39 public:
40   /**
41    * Constructor
42    * @param[in]  gainActor  Ref to the actor that should be set as the one that gains key input focus.
43    * @param[in]  lostActor  Ref to the actor that should be set as the one that loses key input focus.
44    */
45   KeyInputFocusChangedCallback(Control& gainActor, Control& lostActor)
46   : mActorGain(gainActor),
47     mActorLost(lostActor)
48   {
49   }
50
51   void Callback(Control gainingActor, Control lostActor)
52   {
53     mActorGain = gainingActor;
54     mActorLost = lostActor;
55   }
56
57   Control& mActorGain;
58   Control& mActorLost;
59 };
60
61 // Stores data that is populated in the callback and will be read by the TET cases
62 struct SignalData
63 {
64   SignalData()
65   : functorCalled(false)
66   {
67   }
68
69   void Reset()
70   {
71     functorCalled = false;
72
73     receivedKeyEvent.Reset();
74   }
75
76   bool     functorCalled;
77   KeyEvent receivedKeyEvent;
78 };
79
80 /**
81  * Callback class for KeyEvent signal of control.
82  */
83 class KeyEventCallback : public Dali::ConnectionTracker
84 {
85 public:
86   /**
87    * Constructor
88    * @param[in]  returnValue  Set return value of KeyEvent callback.
89    * */
90   KeyEventCallback(bool consumed)
91   : mConsumed(consumed),
92     mIsCalled(false)
93   {
94   }
95
96   bool Callback(Control control, const KeyEvent& keyEvent)
97   {
98     mIsCalled = true;
99     return mConsumed;
100   }
101
102   void Callback(const KeyEvent& keyEvent)
103   {
104     mIsCalled = true;
105   }
106
107   bool mConsumed;
108   bool mIsCalled;
109 };
110
111 } // namespace
112
113 void key_input_focus_manager_startup(void)
114 {
115   test_return_value = TET_UNDEF;
116 }
117
118 void key_input_focus_manager_cleanup(void)
119 {
120   test_return_value = TET_PASS;
121 }
122
123 int UtcDaliKeyInputFocusManagerGet(void)
124 {
125   ToolkitTestApplication application;
126
127   tet_infoline(" UtcDaliKeyInputFocusManagerGet");
128
129   KeyInputFocusManager manager;
130   {
131     manager = KeyInputFocusManager::Get();
132     DALI_TEST_CHECK(manager);
133   }
134
135   KeyInputFocusManager newManager = KeyInputFocusManager::Get();
136   DALI_TEST_CHECK(newManager);
137
138   // Check that focus manager is a singleton
139   DALI_TEST_CHECK(manager == newManager);
140
141   END_TEST;
142 }
143
144 int UtcDaliKeyInputFocusManagerSetFocus01(void)
145 {
146   ToolkitTestApplication application;
147   Integration::Scene     stage = application.GetScene();
148
149   tet_infoline(" Check that there is no focused control. Set focus to control. Check it is now the focused actor and receives KeyInputFocusGained signal");
150
151   KeyInputFocusManager manager = KeyInputFocusManager::Get();
152   DALI_TEST_CHECK(manager);
153
154   Control focusedControl = manager.GetCurrentFocusControl();
155   DALI_TEST_CHECK(!focusedControl);
156
157   DummyControl        dummy     = DummyControl::New(true);
158   Impl::DummyControl& dummyImpl = static_cast<Impl::DummyControl&>(dummy.GetImplementation());
159   dummy.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
160   stage.Add(dummy);
161   DALI_TEST_CHECK(!dummyImpl.keyInputFocusGained);
162
163   manager.SetFocus(dummy);
164   DALI_TEST_CHECK(dummy.HasKeyInputFocus()); // Also tests IsKeyboardListener() API
165   DALI_TEST_CHECK(dummyImpl.keyInputFocusGained);
166
167   focusedControl = manager.GetCurrentFocusControl();
168   DALI_TEST_CHECK(focusedControl);
169   DALI_TEST_CHECK(focusedControl == dummy);
170
171   END_TEST;
172 }
173
174 int UtcDaliKeyInputFocusManagerSetFocus02(void)
175 {
176   ToolkitTestApplication application;
177   Integration::Scene     stage = application.GetScene();
178
179   tet_infoline(" Set focus to control. Check it is now the focused actor and receives KeyInputFocusGained signal. Set focuse to another control - check that the first control receives KeyInputFocusLost");
180
181   KeyInputFocusManager manager = KeyInputFocusManager::Get();
182   DALI_TEST_CHECK(manager);
183
184   DummyControl        dummy1     = DummyControl::New(true);
185   Impl::DummyControl& dummy1Impl = static_cast<Impl::DummyControl&>(dummy1.GetImplementation());
186   dummy1.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
187   stage.Add(dummy1);
188   DALI_TEST_CHECK(!dummy1Impl.keyInputFocusGained);
189   DALI_TEST_CHECK(!dummy1Impl.keyInputFocusLost);
190
191   manager.SetFocus(dummy1);
192   DALI_TEST_CHECK(dummy1.HasKeyInputFocus()); // Also tests IsKeyboardListener() API
193   DALI_TEST_CHECK(dummy1Impl.keyInputFocusGained);
194   dummy1Impl.keyInputFocusGained = false;
195
196   DummyControl        dummy2     = DummyControl::New(true);
197   Impl::DummyControl& dummy2Impl = static_cast<Impl::DummyControl&>(dummy2.GetImplementation());
198   dummy2.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
199   stage.Add(dummy2);
200   DALI_TEST_CHECK(!dummy2Impl.keyInputFocusGained);
201   DALI_TEST_CHECK(!dummy1Impl.keyInputFocusLost);
202
203   manager.SetFocus(dummy2);
204   DALI_TEST_CHECK(dummy2.HasKeyInputFocus()); // Also tests IsKeyboardListener() API
205   DALI_TEST_CHECK(dummy2Impl.keyInputFocusGained);
206   dummy1Impl.keyInputFocusGained = false;
207
208   DALI_TEST_CHECK(!dummy1Impl.keyInputFocusGained);
209   DALI_TEST_CHECK(dummy1Impl.keyInputFocusLost);
210
211   END_TEST;
212 }
213
214 int UtcDaliKeyInputFocusManagerKeyEventPropagation01(void)
215 {
216   ToolkitTestApplication application;
217   Integration::Scene     stage = application.GetScene();
218
219   tet_infoline("Test KeyEvent propagation. If focused control doesn't consume KeyEvent, KeyEvent will be recursively delivered to the control and its parents, until the event is consumed or the stage is reached. In this case, KeyEvent is delivered to KeyboardFocusManager via Stage's KeyEventSignal");
220
221   KeyInputFocusManager manager = KeyInputFocusManager::Get();
222   DALI_TEST_CHECK(manager);
223
224   KeyEventCallback stageCallback(false);
225   stage.KeyEventSignal().Connect(&stageCallback, &KeyEventCallback::Callback);
226
227   DummyControl dummy1 = DummyControl::New(true);
228   dummy1.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
229   KeyEventCallback callback1(false);
230   dummy1.KeyEventSignal().Connect(&callback1, &KeyEventCallback::Callback);
231   stage.Add(dummy1);
232
233   DummyControl dummy2 = DummyControl::New(true);
234   dummy2.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
235   KeyEventCallback callback2(false);
236   dummy2.KeyEventSignal().Connect(&callback2, &KeyEventCallback::Callback);
237   dummy1.Add(dummy2);
238
239   DummyControl        dummy3     = DummyControl::New(true);
240   Impl::DummyControl& dummy3Impl = static_cast<Impl::DummyControl&>(dummy3.GetImplementation());
241   dummy3.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
242   KeyEventCallback callback3(false);
243   dummy3.KeyEventSignal().Connect(&callback3, &KeyEventCallback::Callback);
244   dummy2.Add(dummy3);
245   DALI_TEST_CHECK(!dummy3Impl.keyInputFocusGained);
246   DALI_TEST_CHECK(!dummy3Impl.keyInputFocusLost);
247
248   manager.SetFocus(dummy3);
249   DALI_TEST_CHECK(dummy3Impl.keyInputFocusGained);
250
251   Integration::KeyEvent event("a", "", "a", 0, 0, 0, Integration::KeyEvent::UP, "", "", Device::Class::TOUCH, Device::Subclass::NONE);
252   application.ProcessEvent(event);
253
254   DALI_TEST_CHECK(callback1.mIsCalled);
255   DALI_TEST_CHECK(callback2.mIsCalled);
256   DALI_TEST_CHECK(callback3.mIsCalled);
257   DALI_TEST_CHECK(stageCallback.mIsCalled);
258
259   END_TEST;
260 }
261
262 int UtcDaliKeyInputFocusManagerKeyEventPropagation02(void)
263 {
264   ToolkitTestApplication application;
265   Integration::Scene     stage = application.GetScene();
266
267   tet_infoline("Test KeyEvent propagation. If focused control doesn't consume KeyEvent, KeyEvent will be recursively delivered to the control and its parents, until the event is consumed or the stage is reached. In this case, KeyEvent is delivered from dummy3 to dummy2");
268
269   KeyInputFocusManager manager = KeyInputFocusManager::Get();
270   DALI_TEST_CHECK(manager);
271
272   DummyControl dummy1 = DummyControl::New(true);
273   dummy1.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
274   KeyEventCallback callback1(false);
275   dummy1.KeyEventSignal().Connect(&callback1, &KeyEventCallback::Callback);
276   stage.Add(dummy1);
277
278   DummyControl dummy2 = DummyControl::New(true);
279   dummy2.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
280   KeyEventCallback callback2(true);
281   dummy2.KeyEventSignal().Connect(&callback2, &KeyEventCallback::Callback);
282   dummy1.Add(dummy2);
283
284   DummyControl        dummy3     = DummyControl::New(true);
285   Impl::DummyControl& dummy3Impl = static_cast<Impl::DummyControl&>(dummy3.GetImplementation());
286   dummy3.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
287   KeyEventCallback callback3(false);
288   dummy3.KeyEventSignal().Connect(&callback3, &KeyEventCallback::Callback);
289   dummy2.Add(dummy3);
290   DALI_TEST_CHECK(!dummy3Impl.keyInputFocusGained);
291   DALI_TEST_CHECK(!dummy3Impl.keyInputFocusLost);
292
293   manager.SetFocus(dummy3);
294   DALI_TEST_CHECK(dummy3Impl.keyInputFocusGained);
295
296   Integration::KeyEvent event("a", "", "a", 0, 0, 0, Integration::KeyEvent::UP, "", "", Device::Class::TOUCH, Device::Subclass::NONE);
297   application.ProcessEvent(event);
298
299   DALI_TEST_CHECK(!callback1.mIsCalled);
300   DALI_TEST_CHECK(callback2.mIsCalled);
301   DALI_TEST_CHECK(callback3.mIsCalled);
302
303   END_TEST;
304 }
305
306 int UtcDaliKeyInputFocusManagerDispatchKeyEvents(void)
307 {
308   ToolkitTestApplication application;
309   Integration::Scene     stage = application.GetScene();
310
311   tet_infoline("Test KeyEvents propagation. If DISPATCH_KEY_EVENTS property is false, the KeyEvent is also not received.");
312
313   KeyInputFocusManager manager = KeyInputFocusManager::Get();
314   DALI_TEST_CHECK(manager);
315
316   DummyControl dummy1 = DummyControl::New(true);
317   dummy1.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
318   KeyEventCallback callback1(false);
319   dummy1.KeyEventSignal().Connect(&callback1, &KeyEventCallback::Callback);
320   stage.Add(dummy1);
321
322   DummyControl dummy2 = DummyControl::New(true);
323   dummy2.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
324   KeyEventCallback callback2(false);
325   dummy2.KeyEventSignal().Connect(&callback2, &KeyEventCallback::Callback);
326   // dummy2 set DISPATCH_KEY_EVENTS property to false.
327   dummy2.SetProperty(Toolkit::DevelControl::Property::DISPATCH_KEY_EVENTS, false);
328   dummy1.Add(dummy2);
329
330   DummyControl        dummy3     = DummyControl::New(true);
331   Impl::DummyControl& dummy3Impl = static_cast<Impl::DummyControl&>(dummy3.GetImplementation());
332   dummy3.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
333   KeyEventCallback callback3(false);
334   dummy3.KeyEventSignal().Connect(&callback3, &KeyEventCallback::Callback);
335   dummy2.Add(dummy3);
336   DALI_TEST_CHECK(!dummy3Impl.keyInputFocusGained);
337   DALI_TEST_CHECK(!dummy3Impl.keyInputFocusLost);
338
339   manager.SetFocus(dummy3);
340   DALI_TEST_CHECK(dummy3Impl.keyInputFocusGained);
341
342   Integration::KeyEvent event("a", "", "a", 0, 0, 0, Integration::KeyEvent::UP, "", "", Device::Class::TOUCH, Device::Subclass::NONE);
343   application.ProcessEvent(event);
344
345   DALI_TEST_CHECK(!callback1.mIsCalled);
346   DALI_TEST_CHECK(!callback2.mIsCalled);
347   DALI_TEST_CHECK(!callback3.mIsCalled);
348
349   END_TEST;
350 }
351
352 int UtcDaliKeyInputFocusManagerGetCurrentFocusControl(void)
353 {
354   ToolkitTestApplication application;
355   Integration::Scene     stage = application.GetScene();
356
357   tet_infoline(" Add 2 controls, check they each get focused. Re-focus the first control - ensure it's now got focus (check signals)");
358
359   KeyInputFocusManager manager = KeyInputFocusManager::Get();
360   DALI_TEST_CHECK(manager);
361
362   DummyControl        dummy1     = DummyControl::New(true);
363   Impl::DummyControl& dummy1Impl = static_cast<Impl::DummyControl&>(dummy1.GetImplementation());
364   dummy1.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
365   stage.Add(dummy1);
366   DALI_TEST_CHECK(!dummy1Impl.keyInputFocusGained);
367   DALI_TEST_CHECK(!dummy1Impl.keyInputFocusLost);
368
369   DummyControl        dummy2     = DummyControl::New(true);
370   Impl::DummyControl& dummy2Impl = static_cast<Impl::DummyControl&>(dummy2.GetImplementation());
371   dummy2.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
372   stage.Add(dummy2);
373   DALI_TEST_CHECK(!dummy2Impl.keyInputFocusGained);
374   DALI_TEST_CHECK(!dummy2Impl.keyInputFocusLost);
375
376   manager.SetFocus(dummy1);
377   DALI_TEST_CHECK(dummy1 == manager.GetCurrentFocusControl());
378   DALI_TEST_CHECK(dummy1Impl.keyInputFocusGained);
379   DALI_TEST_CHECK(!dummy1Impl.keyInputFocusLost);
380   dummy1Impl.keyInputFocusGained = false;
381   dummy1Impl.keyInputFocusLost   = false;
382
383   manager.SetFocus(dummy2);
384   DALI_TEST_CHECK(dummy2 == manager.GetCurrentFocusControl());
385   DALI_TEST_CHECK(dummy1Impl.keyInputFocusLost);
386   DALI_TEST_CHECK(dummy2Impl.keyInputFocusGained);
387   DALI_TEST_CHECK(!dummy1Impl.keyInputFocusGained);
388   DALI_TEST_CHECK(!dummy2Impl.keyInputFocusLost);
389   // Reset signal received
390   dummy1Impl.keyInputFocusGained = false;
391   dummy1Impl.keyInputFocusLost   = false;
392   dummy2Impl.keyInputFocusGained = false;
393   dummy2Impl.keyInputFocusLost   = false;
394
395   manager.SetFocus(dummy1);
396   DALI_TEST_CHECK(dummy1 == manager.GetCurrentFocusControl());
397   DALI_TEST_CHECK(dummy1Impl.keyInputFocusGained);
398   DALI_TEST_CHECK(dummy2Impl.keyInputFocusLost);
399   DALI_TEST_CHECK(!dummy1Impl.keyInputFocusLost);
400   DALI_TEST_CHECK(!dummy2Impl.keyInputFocusGained);
401   END_TEST;
402 }
403
404 int UtcDaliKeyInputFocusManagerRemoveFocus(void)
405 {
406   ToolkitTestApplication application;
407   Integration::Scene     stage = application.GetScene();
408
409   tet_infoline(" Add focus controls. Test that removing focus from control which has focus. ");
410
411   KeyInputFocusManager manager = KeyInputFocusManager::Get();
412   DALI_TEST_CHECK(manager);
413
414   DummyControl        dummy1     = DummyControl::New(true);
415   Impl::DummyControl& dummy1Impl = static_cast<Impl::DummyControl&>(dummy1.GetImplementation());
416   dummy1.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
417   stage.Add(dummy1);
418   DALI_TEST_CHECK(!dummy1Impl.keyInputFocusGained);
419   DALI_TEST_CHECK(!dummy1Impl.keyInputFocusLost);
420
421   manager.SetFocus(dummy1);
422   DALI_TEST_CHECK(dummy1 == manager.GetCurrentFocusControl());
423   dummy1Impl.keyInputFocusGained = false;
424   dummy1Impl.keyInputFocusLost   = false;
425
426   manager.RemoveFocus(dummy1);
427   DALI_TEST_CHECK(Control() == manager.GetCurrentFocusControl());
428   DALI_TEST_CHECK(dummy1Impl.keyInputFocusLost);
429   DALI_TEST_CHECK(!dummy1Impl.keyInputFocusGained);
430
431   END_TEST;
432 }
433
434 int UtcDaliKeyInputFocusManagerSignalKeyInputFocusChanged(void)
435 {
436   ToolkitTestApplication application;
437   KeyInputFocusManager   manager = KeyInputFocusManager::Get();
438   Integration::Scene     stage   = application.GetScene();
439
440   tet_infoline(" UtcDaliKeyInputFocusManagerSignalKeyInputFocusChanged");
441
442   PushButton pushButton1 = PushButton::New();
443   PushButton pushButton2 = PushButton::New();
444
445   stage.Add(pushButton1);
446   stage.Add(pushButton2);
447
448   PushButton                   gainActor, lostActor;
449   KeyInputFocusChangedCallback callback(gainActor, lostActor);
450   manager.KeyInputFocusChangedSignal().Connect(&callback, &KeyInputFocusChangedCallback::Callback);
451
452   manager.SetFocus(pushButton1);
453
454   DALI_TEST_CHECK(gainActor == pushButton1);
455   DALI_TEST_CHECK(lostActor == Control());
456
457   gainActor.Reset();
458   lostActor.Reset();
459
460   manager.SetFocus(pushButton2);
461
462   DALI_TEST_CHECK(gainActor == pushButton2);
463   DALI_TEST_CHECK(lostActor == pushButton1);
464
465   gainActor.Reset();
466   lostActor.Reset();
467
468   // Removing the focus actor from the stage would also result in signal emission.
469   stage.Remove(pushButton1);
470   stage.Remove(pushButton2);
471
472   DALI_TEST_CHECK(gainActor == Control());
473   DALI_TEST_CHECK(lostActor == Control());
474   END_TEST;
475 }
476
477 int UtcDaliKeyInputFocusManagerSignalKeyInputFocusChangedforNewWindow(void)
478 {
479   ToolkitTestApplication application;
480   KeyInputFocusManager   manager = KeyInputFocusManager::Get();
481
482   tet_infoline(" UtcDaliKeyInputFocusManagerSignalKeyInputFocusChanged");
483
484   PushButton pushButton1 = PushButton::New();
485   PushButton pushButton2 = PushButton::New();
486
487   Window window = Window::New(PositionSize(0, 0, 0, 0), "", false);
488   DALI_TEST_CHECK(window);
489
490   window.Add(pushButton1);
491   window.Add(pushButton2);
492
493   PushButton                   gainActor, lostActor;
494   KeyInputFocusChangedCallback callback(gainActor, lostActor);
495   manager.KeyInputFocusChangedSignal().Connect(&callback, &KeyInputFocusChangedCallback::Callback);
496
497   manager.SetFocus(pushButton1);
498
499   DALI_TEST_CHECK(gainActor == pushButton1);
500   DALI_TEST_CHECK(lostActor == Control());
501
502   gainActor.Reset();
503   lostActor.Reset();
504
505   manager.SetFocus(pushButton2);
506
507   DALI_TEST_CHECK(gainActor == pushButton2);
508   DALI_TEST_CHECK(lostActor == pushButton1);
509
510   gainActor.Reset();
511   lostActor.Reset();
512
513   // Removing the focus actor from the window would also result in signal emission.
514   window.Remove(pushButton1);
515   window.Remove(pushButton2);
516   DALI_TEST_CHECK(gainActor == Control());
517   DALI_TEST_CHECK(lostActor == Control());
518
519   window.Reset();
520   END_TEST;
521 }