Merge "[N_SE-40957] Set 'transient_for' from the keyboard settings to the target...
[platform/framework/native/uifw.git] / src / app / FApp_UiAppImpl.cpp
1 //
2 // Open Service Platform
3 // Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
4 //
5 // Licensed under the Apache License, Version 2.0 (the License);
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 //     http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17
18 /**
19  * @file        FApp_UiAppImpl.cpp
20  * @brief       This is the implementation for the _UiAppImpl class.
21  */
22
23 #include <appsvc/appsvc.h>
24 #include <bundle.h>
25 #include <glib.h>
26 #include <unique_ptr.h>
27 #include <X11/Xatom.h>
28 #include <X11/Xlib.h>
29
30 #include <FBaseSysLog.h>
31 #include <FBaseColArrayList.h>
32 #include <FAppAppRegistry.h>
33 #include <FUiCtrlFrame.h>
34
35 #include <FBaseRt_Process.h>
36 #include <FUi_ControlImplManager.h>
37 #include <FUi_KeyEventManager.h>
38 #include <FUi_WindowImpl.h>
39 #include <FUi_EcoreEvasMgr.h>
40 #include <FUi_EcoreEvas.h>
41 #include <FUi_UiNotificationEvent.h>
42 #include <FUi_UiEventManager.h>
43 #include <FUiCtrl_FrameImpl.h>
44 #include <FSys_PowerManagerImpl.h>
45 #include <FSys_SettingInfoImpl.h>
46
47 #include "FApp_AppFrame.h"
48 #include "FApp_AppInfo.h"
49 #include "FApp_AppImpl.h"
50 #include "FApp_UiAppImpl.h"
51 #include "FApp_AppArg.h"
52
53 using namespace std;
54 using namespace Tizen::App;
55 using namespace Tizen::Base;
56 using namespace Tizen::Base::Collection;
57 using namespace Tizen::Base::Runtime;
58 using namespace Tizen::Ui;
59 using namespace Tizen::Ui::Controls;
60 using namespace Tizen::System;
61 using namespace Tizen::Graphics;
62
63
64 extern "C" int appsvc_request_transient_app(bundle*, Ecore_X_Window, appsvc_host_res_fn, void*);
65 extern "C" int appcore_set_app_state(int);
66
67 namespace Tizen { namespace App
68 {
69
70 _UiAppImpl* _UiAppImpl::__pUiAppImpl = null;
71
72
73 _UiAppImpl::_UiAppImpl(UiApp* pUiApp)
74         : __pAppFrame(null)
75         , __pAppImpl(_AppImpl::GetInstance())
76         , __appUiState(APP_UI_STATE_BACKGROUND)
77         , __pFrameList(null)
78         , __pUiApp(pUiApp)
79 {
80         __pUiAppImpl = this;
81         __pFrameList = new (std::nothrow) ArrayList();
82         SysTryReturnVoidResult(NID_APP, __pFrameList != null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Insufficient memory.");
83         __pFrameList->Construct();
84         SysTryReturnVoidResult(NID_APP, __pAppImpl != null, E_INVALID_STATE, "[E_INVALID_STATE] Getting internal instance failed.");
85 }
86
87
88 _UiAppImpl::~_UiAppImpl(void)
89 {
90         RemoveAllFrames();
91
92         delete __pAppFrame;
93         __pUiAppImpl = null;
94 }
95
96
97 bool
98 _UiAppImpl::OnCreate(void)
99 {
100         SysLog(NID_APP, "Platform creation event.");
101
102         _AppInfo::SetAppState(INITIALIZING);
103
104         return true;
105 }
106
107
108 void
109 _UiAppImpl::RaiseFrame(Frame& frame)
110 {
111         _FrameImpl* pFrameImpl = _FrameImpl::GetInstance(frame);
112
113         if (pFrameImpl)
114         {
115                 // [N_SE-39536] Window raise is requested as synchronous due to B/S issue
116                 _EcoreEvas* pEvas = GetEcoreEvasMgr()->GetEcoreEvas();
117                 if (pEvas)
118                 {
119                         pEvas->ActivateWindow(pFrameImpl->GetCore());
120                 }
121         }
122 }
123
124
125 long
126 _UiAppImpl::GetTargetWindowHandle(void) const
127 {
128         result r = E_SUCCESS;
129
130         _EcoreEvasMgr* pEcoreEvasMgr = GetEcoreEvasMgr();
131         r = GetLastResult();
132         SysTryReturn(NID_APP, pEcoreEvasMgr, -1, r, "Propagating.");
133
134         _EcoreEvas* pEcoreEvas = pEcoreEvasMgr->GetEcoreEvas();
135         r = GetLastResult();
136         SysTryReturn(NID_APP, pEcoreEvas, -1, r, "Propagating.");
137
138         Atom actualTypeReturn;
139         int actualFormatReturn;
140         unsigned long nItemsReturn;
141         unsigned long bytesAfterReturn;
142         unsigned char* pPropReturn = null;
143
144     gint ret = 0;
145     ret = XGetWindowProperty(static_cast<Display*>(ecore_x_display_get()),
146                                                         ecore_x_window_root_get(pEcoreEvas->GetXWindow()),
147                                                         ecore_x_atom_get("_ISF_ACTIVE_WINDOW"),
148                                                         0,
149                                                         G_MAXLONG,
150                                                         false,
151                                                         XA_WINDOW,
152                                                         &actualTypeReturn,
153                                                         &actualFormatReturn,
154                                                         &nItemsReturn,
155                                                         &bytesAfterReturn,
156                                                         &pPropReturn);
157         SysTryReturn(NID_APP, ret == Success, -1, E_SYSTEM, "A failure occurs from the underlying system.");
158
159         Ecore_X_Window targetWindow = 0;
160
161         if (pPropReturn)
162         {
163                 if (actualTypeReturn == XA_WINDOW)
164                 {
165                         targetWindow = *(reinterpret_cast<Ecore_X_Window*>(pPropReturn));
166                         SysLog(NID_APP, "The handle of the target window is %x.", targetWindow);
167                 }
168
169                 XFree(pPropReturn);
170         }
171
172         return targetWindow? targetWindow: -1;
173 }
174
175
176 static int
177 TransientResponseCb(void* pData)
178 {
179         SysLog(NID_APP, "Handling cleanup for submode app.");
180
181         // platform invokes ecore_main_loop_quit() after returning this callback
182         return 0;
183 }
184
185 void
186 _UiAppImpl::OnService(service_s* service, bool initial)
187 {
188         Frame* pFrame = dynamic_cast<Frame*>(__pFrameList->GetAt(0));
189         _EcoreEvas* pEvas = GetEcoreEvasMgr()->GetEcoreEvas();
190
191         // make OnForeground event
192         if (pFrame != null)
193         {
194                 // handle submode
195                 if (pEvas && _AppInfo::IsSubMode())
196                 {
197                         _FrameImpl* pFrameImpl = _FrameImpl::GetInstance(*pFrame);
198                         if (pFrameImpl != null)
199                         {
200                                 const unsigned int curHandle = pFrameImpl->GetNativeHandle();
201
202                                 bundle* pBundle = _AppArg::GetBundleFromSvc(service);
203                                 const int pid = _AppArg::GetCallerPid(pBundle);
204                                 if (pid <= 0 || ((kill(pid, 0) < 0) && errno == ESRCH))
205                                 {
206                                         SysLogException(NID_APP, E_SYSTEM, "Caller process %d not exist : terminating %d.", pid, getpid());
207                                         _Process::Exit(-1);
208                                 }
209
210                                 int ret = appsvc_request_transient_app(pBundle, curHandle, TransientResponseCb, NULL);
211
212                                 SysLog(NID_APP, "Transient sets for (0x%x) with result (%d).", curHandle, ret);
213                         }
214                 }
215
216                 if (initial)
217                 {
218                         const int type = _AppInfo::GetAppType();
219                         if (type & _APP_TYPE_IME_APP)
220                         {
221                                 SysLog(NID_APP, "Skipping 1st resume for IME app.");
222                         }
223                         else
224                         {
225                                 OnResume();
226                         }
227                 }
228         }
229
230         // [INFO] to confirm that the window is not foreground
231         if (pEvas)
232         {
233                 int pid = pEvas->GetProcessId(pEvas->GetActiveWindow());
234                 SysLog(NID_APP, "%d -> %d", pid, _AppInfo::GetProcessId());
235                 if (pid != _AppInfo::GetProcessId())
236                 {
237                         if (!initial)
238                         {
239                                 if (pFrame != null)
240                                 {
241                                         _FrameImpl* pFrameImpl = _FrameImpl::GetInstance(*pFrame);
242
243                                         // [FIXME] Multi window handling
244                                         if (pFrameImpl != null)
245                                         {
246                                                 //pEvas->ActivateWindow(pFrameImpl->GetCore());
247
248                                                 unique_ptr<ArrayList> pEventArgs(new (std::nothrow) ArrayList());
249                                                 SysTryReturnVoidResult(NID_APP, pEventArgs, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Memory is insufficient.");
250                                                 pEventArgs->Construct();
251
252                                                 unique_ptr<String> pString(new (std::nothrow) Tizen::Base::String(L"ActivateFrame"));
253                                                 SysTryReturnVoidResult(NID_APP, pString, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Memory is insufficient.");
254
255                                                 pEventArgs->Add(*(pString.get()));
256
257                                                 _UiNotificationEvent event(pFrameImpl->GetCore().GetHandle(), pEventArgs.get());
258
259                                                 result r = _UiEventManager::GetInstance()->PostEvent(event);
260                                                 SysTryReturnVoidResult(NID_APP, r == E_SUCCESS, E_SYSTEM, "[E_SYSTEM] A system error occurred.");
261
262                                                 pString.release();
263                                                 pEventArgs.release();
264
265                                                 // N_SE-24616, N_SE-24383 for OnForground() and visibility issue
266                                                 OnResume();
267                                         }
268                                 }
269                         }
270                 }
271         }
272 }
273
274
275 void
276 _UiAppImpl::OnTerminate(void)
277 {
278         SysLog(NID_APP, "Termination event 0x%x state", _AppInfo::GetAppState());
279
280         if (__pUiApp->GetAppUiState() == APP_UI_STATE_FOREGROUND)
281         {
282                 OnPause();
283         }
284
285         if (OnUiAppImplTerminating() != true)
286         {
287                 SysLog(NID_APP, "[E_SYSTEM] The Termination of application failed.");
288         }
289 }
290
291
292 void
293 _UiAppImpl::OnResume(void)
294 {
295         SysLog(NID_APP, "System resume event on 0x%x state", _AppInfo::GetAppState());
296
297         if (_AppInfo::GetAppState() == RUNNING)
298         {
299                 OnForeground();
300         }
301 }
302
303
304 void
305 _UiAppImpl::OnPause(void)
306 {
307         SysLog(NID_APP, "System pause event on 0x%x state", _AppInfo::GetAppState());
308
309         if (_AppInfo::GetAppState() == RUNNING)
310         {
311                 OnBackground();
312         }
313 }
314
315
316 result
317 _UiAppImpl::OnFrameRaiseRequested(void)
318 {
319         SysLog(NID_APP, "Frame raise is requested.");
320
321         Frame* pFrame = null;
322         if (__pFrameList == null || (pFrame = dynamic_cast<Frame*>(__pFrameList->GetAt(0))) == null)
323         {
324                 SysLog(NID_APP, "No frame is available.");
325                 return E_SUCCESS;
326         }
327
328         if (__appUiState == APP_UI_STATE_FOREGROUND)
329         {
330                 SysLog(NID_APP, "Already foreground state.");
331                 return E_SUCCESS;
332         }
333
334         RaiseFrame(*pFrame);
335         return E_SUCCESS;
336 }
337
338
339 long
340 _UiAppImpl::OnWindowHandleRequest(void)
341 {
342         long handle = -1;
343         int type = _AppInfo::GetAppType();
344
345         if (type & _APP_TYPE_IME_APP)
346         {
347                 handle = GetTargetWindowHandle();
348         }
349         else
350         {
351                 const _EcoreEvas* const pEvas = GetEcoreEvasMgr()->GetEcoreEvas();
352                 handle = (pEvas) ? static_cast<long>(pEvas->GetXWindow()) : -1;
353         }
354
355         return handle;
356 }
357
358
359 result
360 _UiAppImpl::AddFrame(const Frame& frame)
361 {
362         result r = E_SUCCESS;
363         Frame& tmpFrame = const_cast <Frame&>(frame);
364
365         SysTryReturnResult(NID_APP, __pFrameList != null, E_INVALID_STATE, "Getting FrameList failed.");
366         SysTryReturnResult(NID_APP, !__pFrameList->Contains(tmpFrame), E_OBJ_ALREADY_EXIST, "The frame is already registered.");
367
368         _WindowImpl* pFrameImpl = _WindowImpl::GetInstance(tmpFrame);
369         SysTryReturnResult(NID_APP, pFrameImpl != null, E_INVALID_ARG, "The frame is not constructed yet.");
370
371         __pFrameList->Add(tmpFrame);
372         r = pFrameImpl->Open(false); // Attach to the main tree without 'draw & show'.
373         if (IsFailed(r))
374         {
375                 SysLog(NID_UI, "Failed to attach frame.");
376                 __pFrameList->Remove(tmpFrame);
377         }
378
379         return r;
380 }
381
382
383 IAppFrame*
384 _UiAppImpl::GetAppFrame(void)
385 {
386         SysTryReturn(NID_APP, __pFrameList != null, null, E_INVALID_STATE, "[E_INVALID_STATE] Getting FrameList failed.");
387         int frameCount = __pFrameList->GetCount();
388
389         if (frameCount <= 0)
390         {
391                 SysLogException(NID_APP, E_OBJ_NOT_FOUND, "There is no frame !!! use AddFrame() before call GetAppFrame()");
392                 SysAssertf(false, "There is no frame !!! use AddFrame() before call GetAppFrame()");
393         }
394
395         Frame* pFrame = dynamic_cast <Frame*>(__pFrameList->GetAt(frameCount - 1));
396
397         if (pFrame == null)
398         {
399                 SysLogException(NID_APP, E_OBJ_NOT_FOUND, "There is no frame !!! use AddFrame() before call GetAppFrame()");
400                 SysAssertf(false, "There is no frame !!! use AddFrame() before call GetAppFrame()");
401         }
402
403         if (__pAppFrame == null)
404         {
405                 __pAppFrame = new (std::nothrow) _AppFrame(*pFrame);
406                 SysTryReturn(NID_APP, __pAppFrame != null, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Insufficient memory.");
407                 __pAppFrame->Construct();
408         }
409         else if (__pAppFrame->GetFrame() != pFrame)
410         {
411                 __pAppFrame->SetFrame(pFrame);
412         }
413
414         return __pAppFrame;
415 }
416
417
418 result
419 _UiAppImpl::RemoveFrame(const Frame& frame)
420 {
421         result r = E_SUCCESS;
422         SysTryReturnResult(NID_APP, __pFrameList != null, E_INVALID_STATE, "Getting FrameList failed.");
423
424         Frame& tmpFrame = const_cast <Frame&>(frame);
425         _WindowImpl* pFrameImpl = _WindowImpl::GetInstance(tmpFrame);
426
427         r = __pFrameList->Remove(frame, false);
428
429         if (pFrameImpl)
430         {
431                 pFrameImpl->Destroy();
432         }
433
434         return r;
435 }
436
437
438 result
439 _UiAppImpl::RemoveAllFrames(void)
440 {
441         result r = E_SUCCESS;
442         SysTryReturnResult(NID_APP, __pFrameList != null, E_INVALID_STATE, "Getting FrameList failed.");
443
444         int frameCount = __pFrameList->GetCount();
445         for (int i = 0; i < frameCount; i++)
446         {
447                 Frame* pFrame = dynamic_cast <Frame*>(__pFrameList->GetAt(i));
448                 if (pFrame)
449                 {
450                         _WindowImpl* pFrameImpl = _WindowImpl::GetInstance(*pFrame);
451                         if (pFrameImpl)
452                         {
453                                 pFrameImpl->Destroy();
454                         }
455                 }
456         }
457
458         if (__pFrameList->GetCount() > 0)
459         {
460                 __pFrameList->RemoveAll(false);
461         }
462
463         delete __pFrameList;
464         __pFrameList = null;
465
466         return r;
467 }
468
469
470 IList*
471 _UiAppImpl::GetFrameList(void)
472 {
473         return __pFrameList;
474 }
475
476
477 Frame*
478 _UiAppImpl::GetFrame(const String& name)
479 {
480         Frame* pFrame = null;
481         SysTryReturn(NID_APP, __pFrameList != null, null, E_INVALID_STATE, "[E_INVALID_STATE] Getting FrameList failed.");
482         int frameCount = __pFrameList->GetCount();
483
484         for (int i = 0; i < frameCount; i++)
485         {
486                 pFrame = dynamic_cast <Frame*>(__pFrameList->GetAt(i));
487
488                 if (pFrame != null && pFrame->GetName() == name)
489                 {
490                         return pFrame;
491                 }
492         }
493
494         return null;
495 }
496
497
498 Frame*
499 _UiAppImpl::GetFrameAt(int index)
500 {
501         Frame* pFrame = null;
502         SysTryReturn(NID_APP, __pFrameList != null, null, E_INVALID_STATE, "[E_INVALID_STATE] Getting FrameList failed.");
503         SysTryReturn(NID_APP, index >= 0, null, E_OUT_OF_RANGE, "[E_OUT_OF_RANGE] The index is less than 0.");
504
505         int frameCount = __pFrameList->GetCount();
506         SysTryReturn(NID_APP, index < frameCount, null, E_OUT_OF_RANGE, "[E_OUT_OF_RANGE] The index is greater than the number of frames.");
507
508         pFrame = dynamic_cast <Frame*>(__pFrameList->GetAt(index));
509
510         return pFrame;
511 }
512
513 bool
514 _UiAppImpl::OnAppInitializing(void)
515 {
516         // Do Ui related initializing for UiApp
517         result r = InitializeUiFramework();
518         if (IsFailed(r))
519         {
520                 SysLogException(NID_APP, E_SYSTEM, "Getting resolution information failure. Application may not be installed correctly.");
521                 _Process::Exit(-1);
522         }
523
524         _KeyEventManager* pKeyManager = _KeyEventManager::GetInstance();
525         if (pKeyManager)
526         {
527                 pKeyManager->AddKeyEventListener(*this);
528         }
529
530         // API versioning for initial frame creation
531         if (_AppInfo::GetApiVersion() == _API_VERSION_2_0 && _AppInfo::IsOspCompat())
532         {       // if API version is less than 3.0, create initial frame
533                 Frame* pDefaultFrame = new (std::nothrow) Frame();
534                 SysTryReturn(NID_APP, pDefaultFrame != null, false, r = E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Frame creation failed.");
535                 pDefaultFrame->Construct();
536                 AddFrame(*pDefaultFrame);
537                 SysLog(NID_APP, "Default frame is added for API version %d Compatibility.", _AppInfo::GetApiVersion());
538         }
539
540         SysTryReturn(NID_APP, __pUiApp != null, false, E_INVALID_STATE, "[E_INVALID_STATE] Getting UiApp instance failed.");
541
542         SysLog(NID_APP, "Entering user OnAppInitializing().");
543         const bool bReturn = __pUiApp->OnAppInitializing(*(AppRegistry::GetInstance()));
544
545         SysLog(NID_APP, "Back to the platform initializing routine.");
546         _SettingInfoImpl::AddSettingEventListenerForInternal(*this);
547         return bReturn;
548 }
549
550
551 bool
552 _UiAppImpl::OnAppInitialized(void)
553 {
554         SysTryReturn(NID_APP, __pUiApp != null, false, E_INVALID_STATE, "[E_INVALID_STATE] Getting UiApp instance failed.");
555
556         const bool b = __pUiApp->OnAppInitialized();
557
558         Frame* pFrame = dynamic_cast<Frame*>(__pFrameList->GetAt(0));
559         if (pFrame)
560         {
561                 int type = _AppInfo::GetAppType();
562                 if (type & _APP_TYPE_IME_APP)
563                 {
564                         SysLog(NID_APP, "Defering frame update for IME app.");
565                         pFrame->SetShowState(false);
566                         appcore_set_app_state(3);
567                 }
568         }
569
570         if (b)
571         {
572                 if (__pFrameList->GetCount() > 0)
573                 {
574                         return true;
575                 }
576                 else
577                 {
578                         SysLogException(NID_APP, E_OBJ_NOT_FOUND, "There is no frame !!! use AddFrame() before returning OnAppInitialized()");
579                         SysAssertf(false, "There is no frame !!! use AddFrame() before returning OnAppInitialized()");
580                 }
581         }
582         return false;
583 }
584
585
586 bool
587 _UiAppImpl::OnUiAppImplTerminating(void)
588 {
589         bool result = false;
590
591         RemoveAllFrames();
592
593         if (_AppInfo::GetAppState() != TERMINATED)
594         {
595                 result = __pUiApp->OnAppTerminating(*(AppRegistry::GetInstance()), __pAppImpl->IsForcedTermination());
596                 _AppInfo::SetAppState(TERMINATED);
597         }
598
599         // Do Ui related finalizing for UiApp
600         FinalizeUiFramework();
601
602         return result;
603 }
604
605
606 bool
607 _UiAppImpl::OnKeyPressed(const _Control& source, const _KeyInfo& keyInfo)
608 {
609         return false;
610 }
611
612
613 bool
614 _UiAppImpl::OnKeyReleased(const _Control& source, const _KeyInfo& keyInfo)
615 {
616         if (__appUiState == APP_UI_STATE_FOREGROUND)
617         {
618                 if (keyInfo.GetKeyCode() == _KEY_END)
619                 {
620                         SysTryReturn(NID_APP, __pUiApp != null, false, E_INVALID_STATE, "[E_INVALID_STATE] Getting UI App instance failed.");
621
622                         if (__pUiApp->OnAppWillTerminate())
623                         {
624                                 __pUiApp->Terminate();
625                                 return true;
626                         }
627                 }
628         }
629         return false;
630 }
631
632
633 void
634 _UiAppImpl::OnForeground(void)
635 {
636         result r = E_SUCCESS;
637
638         SysLog(NID_APP, "Invoking application callback.");
639
640         __appUiState = APP_UI_STATE_FOREGROUND;
641         __pUiApp->OnForeground();
642
643         SysLog(NID_APP, "Returned from application callback.");
644
645         r = _PowerManagerImpl::OnForeground();
646
647         SysTryLog(NID_APP, !IsFailed(r), "Failed to send foreground event to powermanager");
648 }
649
650
651 void
652 _UiAppImpl::OnBackground(void)
653 {
654         result r = E_SUCCESS;
655
656         SysLog(NID_APP, "Invoking application callback.");
657
658         __appUiState = APP_UI_STATE_BACKGROUND;
659         __pUiApp->OnBackground();
660
661         SysLog(NID_APP, "Returned from application callback.");
662
663         r = _PowerManagerImpl::OnBackground();
664
665         SysTryLog(NID_APP, !IsFailed(r), "Failed to send background event to powermanager");
666 }
667
668
669 AppUiState
670 _UiAppImpl::GetAppUiState(void) const
671 {
672         return __appUiState;
673 }
674
675
676 _UiAppImpl*
677 _UiAppImpl::GetInstance(void)
678 {
679         return __pUiAppImpl;
680 }
681
682
683 UiApp*
684 _UiAppImpl::GetUiAppInstance(void)
685 {
686         return __pUiApp;
687 }
688
689 void
690 _UiAppImpl::OnSettingChanged(String& key)
691 {
692         SysLog(NID_APP,"Changed Key: %ls", key.GetPointer());
693
694         if (key == L"http://tizen.org/setting/locale.language")
695         {
696                 _AppImpl::OnLanguageChanged(null);
697         }
698 }
699
700 } } //Tizen::App