Merge "Fix svace issue for image-operator" into devel/master
[platform/core/uifw/dali-adaptor.git] / dali / internal / input / common / key-impl.cpp
1 /*
2  * Copyright (c) 2023 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 <dali/internal/input/common/key-impl.h>
20
21 // EXTERNAL INCLUDES
22 #include <dlfcn.h>
23 #include <string.h>
24 #include <iostream>
25 #include <map>
26
27 #include <dali/integration-api/debug.h>
28
29 namespace Dali
30 {
31 namespace Internal
32 {
33 namespace Adaptor
34 {
35 namespace KeyLookup
36 {
37 namespace
38 {
39 #if defined(DEBUG_ENABLED)
40 Debug::Filter* gKeyExtensionLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_KEY_EXTENSION");
41 #endif
42
43 // Path for loading extension keys
44 const char* KEY_EXTENSION_PLUGIN_SO("libdali2-key-extension.so");
45
46 class KeyMap
47 {
48 public:
49   KeyMap()
50   : mExtensionKeyLookupTable(NULL),
51     mPlugin(NULL),
52     mHandle(NULL),
53     mCreateKeyExtensionPluginPtr(NULL),
54     mDestroyKeyExtensionPluginPtr(NULL),
55     mLookup(cmpString),
56     mExtensionLookup(cmpString),
57     mExtensionLookupCount(0),
58     mIsLookupTableInitialized(false),
59     mIsExtensionLookupTableInitialized(false)
60   {
61   }
62
63   ~KeyMap()
64   {
65     if(mHandle != NULL)
66     {
67       if(mDestroyKeyExtensionPluginPtr != NULL)
68       {
69         mDestroyKeyExtensionPluginPtr(mPlugin);
70       }
71
72       dlclose(mHandle);
73     }
74   }
75
76   int GetDaliKeyEnum(const char* keyName)
77   {
78     // If lookup table is not initialized, initialize lookup table
79     if(!mIsLookupTableInitialized)
80     {
81       InitializeLookupTable();
82     }
83
84     Lookup::const_iterator i = mLookup.find(keyName);
85
86     if(i == mLookup.end())
87     {
88       // If cannot find target, find it at the extension
89       // If extension lookup table is not initialized, initialize extension lookup table
90       if(!mIsExtensionLookupTableInitialized)
91       {
92         InitializeExtensionLookupTable();
93       }
94
95       // Find at extension
96       i = mExtensionLookup.find(keyName);
97
98       if(i == mExtensionLookup.end())
99       {
100         return -1;
101       }
102       else
103       {
104         return (*i).second.first;
105       }
106     }
107     else
108     {
109       return (*i).second.first;
110     }
111   }
112
113   const char* GetKeyName(int daliKeyCode)
114   {
115     // If lookup table is not initialized, initialize lookup table
116     if(!mIsLookupTableInitialized)
117     {
118       InitializeLookupTable();
119     }
120
121     for(size_t i = 0; i < KEY_LOOKUP_COUNT; ++i)
122     {
123       if(KeyLookupTable[i].daliKeyCode == daliKeyCode)
124       {
125         return KeyLookupTable[i].keyName;
126       }
127     }
128
129     // If extension lookup table is not initialized, initialize extension lookup table
130     if(!mIsExtensionLookupTableInitialized)
131     {
132       InitializeExtensionLookupTable();
133     }
134
135     for(size_t i = 0; i < mExtensionLookupCount; ++i)
136     {
137       if(mExtensionKeyLookupTable[i].daliKeyCode == daliKeyCode)
138       {
139         return mExtensionKeyLookupTable[i].keyName;
140       }
141     }
142
143     return NULL;
144   }
145
146   bool IsDeviceButton(const char* keyName)
147   {
148     // If lookup table is not initialized, initialize lookup table
149     if(!mIsLookupTableInitialized)
150     {
151       InitializeLookupTable();
152     }
153
154     Lookup::const_iterator i = mLookup.find(keyName);
155     if(i == mLookup.end())
156     {
157       // If cannot find target, find it at the extension.
158       // If extension lookup table is not initialized, initialize extension lookup table
159       if(!mIsExtensionLookupTableInitialized)
160       {
161         InitializeExtensionLookupTable();
162       }
163
164       // Find at extension
165       i = mExtensionLookup.find(keyName);
166
167       if(i == mExtensionLookup.end())
168       {
169         return false;
170       }
171       else
172       {
173         return (*i).second.second;
174       }
175     }
176     else
177     {
178       return (*i).second.second;
179     }
180
181     return false;
182   }
183
184 private:
185   void InitializeLookupTable()
186   {
187     // create the lookup
188     for(size_t i = 0; i < KEY_LOOKUP_COUNT; ++i)
189     {
190       mLookup[KeyLookupTable[i].keyName] = DaliKeyType(KeyLookupTable[i].daliKeyCode, KeyLookupTable[i].deviceButton);
191     }
192
193     mIsLookupTableInitialized = true;
194   }
195
196   void InitializeExtensionLookupTable()
197   {
198     // Try to load extension keys
199     char* error = NULL;
200     mHandle     = dlopen(KEY_EXTENSION_PLUGIN_SO, RTLD_NOW);
201     error       = dlerror();
202
203     if(mHandle == NULL)
204     {
205       DALI_LOG_INFO(gKeyExtensionLogFilter, Debug::General, "Failed to get handle from libdali2-key-extension.so\n");
206       return;
207     }
208
209     if(error != NULL)
210     {
211       DALI_LOG_INFO(gKeyExtensionLogFilter, Debug::General, "dlopen got error: %s  \n", error);
212       return;
213     }
214
215     mCreateKeyExtensionPluginPtr = reinterpret_cast<CreateKeyExtensionPluginFunction>(dlsym(mHandle, "CreateKeyExtensionPlugin"));
216     if(mCreateKeyExtensionPluginPtr == NULL)
217     {
218       DALI_LOG_INFO(gKeyExtensionLogFilter, Debug::General, "Failed to get CreateKeyExtensionPlugin function\n");
219       return;
220     }
221
222     mPlugin = mCreateKeyExtensionPluginPtr();
223     if(mPlugin == NULL)
224     {
225       DALI_LOG_INFO(gKeyExtensionLogFilter, Debug::General, "Failed to create plugin object\n");
226       return;
227     }
228
229     mDestroyKeyExtensionPluginPtr = reinterpret_cast<DestroyKeyExtensionPluginFunction>(dlsym(mHandle, "DestroyKeyExtensionPlugin"));
230     if(mDestroyKeyExtensionPluginPtr == NULL)
231     {
232       DALI_LOG_INFO(gKeyExtensionLogFilter, Debug::General, "Failed to get DestroyKeyExtensionPlugin function\n");
233       return;
234     }
235
236     mExtensionKeyLookupTable = mPlugin->GetKeyLookupTable();
237     mExtensionLookupCount    = mPlugin->GetKeyLookupTableCount();
238
239     // Add extension keys to lookup
240     for(size_t i = 0; i < mExtensionLookupCount; ++i)
241     {
242       mExtensionLookup[mExtensionKeyLookupTable[i].keyName] = DaliKeyType(mExtensionKeyLookupTable[i].daliKeyCode, mExtensionKeyLookupTable[i].deviceButton);
243     }
244
245     mIsExtensionLookupTableInitialized = true;
246   }
247
248   /**
249    * compare function, to compare string by pointer
250    */
251   static bool cmpString(const char* a, const char* b)
252   {
253     return strcmp(a, b) < 0;
254   }
255
256   KeyExtensionPlugin::KeyLookup* mExtensionKeyLookupTable;                             ///< Lookup table for extension keys
257   Dali::KeyExtensionPlugin*      mPlugin;                                              ///< Key extension plugin handle
258   void*                          mHandle;                                              ///< Handle for the loaded library
259   typedef Dali::KeyExtensionPlugin* (*CreateKeyExtensionPluginFunction)();             ///< Type of function pointer to get KeyExtensionPlugin object
260   typedef void (*DestroyKeyExtensionPluginFunction)(Dali::KeyExtensionPlugin* plugin); ///< Type of function pointer to delete KeyExtensionPlugin object
261   CreateKeyExtensionPluginFunction  mCreateKeyExtensionPluginPtr;                      ///< Function pointer to get KeyExtensionPlugin object
262   DestroyKeyExtensionPluginFunction mDestroyKeyExtensionPluginPtr;                     ///< Function pointer to delete KeyExtensionPlugin object
263
264   typedef std::pair<int, bool> DaliKeyType;
265
266   typedef std::map<const char* /* key name */, DaliKeyType /* key code */, bool (*)(char const* a, char const* b)> Lookup;
267
268   Lookup mLookup;
269   Lookup mExtensionLookup;
270   size_t mExtensionLookupCount;              ///< count of extension lookup table
271   bool   mIsLookupTableInitialized;          ///< flag for basic lookup table initialization
272   bool   mIsExtensionLookupTableInitialized; ///< flag for extension lookup table initialization
273 };
274
275 KeyMap& GetKeyMap()
276 {
277   static KeyMap globalKeyLookup;
278   return globalKeyLookup;
279 }
280 } // namespace
281
282 bool IsKey(const Dali::KeyEvent& keyEvent, Dali::KEY daliKey)
283 {
284   int key = GetKeyMap().GetDaliKeyEnum(keyEvent.GetKeyName().c_str());
285   return daliKey == key;
286 }
287
288 bool IsDeviceButton(const char* keyName)
289 {
290   return GetKeyMap().IsDeviceButton(keyName);
291 }
292
293 const char* GetKeyName(Dali::KEY daliKey)
294 {
295   return GetKeyMap().GetKeyName(daliKey);
296 }
297
298 int GetDaliKeyCode(const char* keyName)
299 {
300   return GetKeyMap().GetDaliKeyEnum(keyName);
301 }
302
303 } // namespace KeyLookup
304
305 } // namespace Adaptor
306
307 } // namespace Internal
308
309 } // namespace Dali