Updated all code to new format
[platform/core/uifw/dali-adaptor.git] / dali / internal / window-system / windows / platform-implement-win.cpp
1 /*
2 * Copyright (c) 2021 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/window-system/windows/platform-implement-win.h>
20
21 // EXTERNAL INCLUDES
22 #include <windows.h>
23 #include <map>
24
25 // INTERNAL INCLUDES
26 #include <dali/internal/window-system/windows/event-system-win.h>
27
28 namespace
29 {
30 constexpr float INCH = 25.4;
31 }
32
33 namespace Dali
34 {
35 namespace Internal
36 {
37 namespace Adaptor
38 {
39 namespace WindowsPlatform
40 {
41 LRESULT CALLBACK WinProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
42 {
43   WindowImpl::ProcWinMessage(reinterpret_cast<uint64_t>(hWnd), uMsg, wParam, lParam);
44
45   LRESULT ret = DefWindowProc(hWnd, uMsg, wParam, lParam);
46   return ret;
47 }
48
49 namespace
50 {
51 const std::string DALI_WINDOW_CLASS_NAME = "DaliWindow";
52
53 uint32_t sNumWindows = 0;
54
55 void EnsureWindowClassRegistered()
56 {
57   if(sNumWindows == 0)
58   {
59     WNDCLASS cs      = {0};
60     cs.cbClsExtra    = 0;
61     cs.cbWndExtra    = 0;
62     cs.hbrBackground = (HBRUSH)(COLOR_WINDOW + 2);
63     cs.hCursor       = NULL;
64     cs.hIcon         = NULL;
65     cs.hInstance     = GetModuleHandle(NULL);
66     cs.lpfnWndProc   = (WNDPROC)WinProc;
67     cs.lpszClassName = DALI_WINDOW_CLASS_NAME.c_str();
68     cs.lpszMenuName  = NULL;
69     cs.style         = CS_VREDRAW | CS_HREDRAW;
70     RegisterClass(&cs);
71   }
72 }
73
74 void EnsureWindowClassUnregistered()
75 {
76   if(sNumWindows == 0)
77   {
78     UnregisterClass(DALI_WINDOW_CLASS_NAME.c_str(), GetModuleHandle(NULL));
79   }
80 }
81
82 std::map<uint64_t, WindowImpl*> sHWndToListener;
83
84 void RemoveListener(uint64_t hWnd)
85 {
86   std::map<uint64_t, WindowImpl*>::iterator x = sHWndToListener.find(hWnd);
87   if(sHWndToListener.end() != x)
88   {
89     sHWndToListener.erase(x);
90   }
91 }
92
93 } // namespace
94
95 const uint32_t WindowImpl::STYLE       = WS_OVERLAPPED;
96 const int32_t  WindowImpl::EDGE_WIDTH  = 8;
97 const int32_t  WindowImpl::EDGE_HEIGHT = 18;
98
99 WindowImpl::WindowImpl()
100 {
101   colorDepth = -1;
102   mHWnd      = 0;
103   mHdc       = 0;
104   listener   = NULL;
105 }
106
107 WindowImpl::~WindowImpl()
108 {
109   RemoveListener(mHWnd);
110 }
111
112 void WindowImpl::ProcWinMessage(uint64_t hWnd, uint32_t uMsg, uint64_t wParam, uint64_t lParam)
113 {
114   std::map<uint64_t, WindowImpl*>::iterator x = sHWndToListener.find(hWnd);
115
116   if(sHWndToListener.end() != x)
117   {
118     CallbackBase* listener = x->second->listener;
119
120     if(NULL != listener)
121     {
122       TWinEventInfo eventInfo(hWnd, uMsg, wParam, lParam);
123       CallbackBase::Execute(*listener, &eventInfo);
124     }
125   }
126 }
127
128 void WindowImpl::GetDPI(float& xDpi, float& yDpi)
129 {
130   HDC hdcScreen = GetDC(reinterpret_cast<HWND>(mHWnd));
131
132   int32_t iX    = GetDeviceCaps(hdcScreen, HORZRES);  // pixel
133   int32_t iY    = GetDeviceCaps(hdcScreen, VERTRES);  // pixel
134   int32_t iPhsX = GetDeviceCaps(hdcScreen, HORZSIZE); // mm
135   int32_t iPhsY = GetDeviceCaps(hdcScreen, VERTSIZE); // mm
136
137   xDpi = static_cast<float>(iX) / static_cast<float>(iPhsX) * INCH;
138   yDpi = static_cast<float>(iY) / static_cast<float>(iPhsY) * INCH;
139 }
140
141 int WindowImpl::GetColorDepth()
142 {
143   DALI_ASSERT_DEBUG(colorDepth >= 0 && "HWND hasn't been created, no color depth");
144   return colorDepth;
145 }
146
147 uint64_t WindowImpl::CreateHwnd(
148   _In_opt_ const char* lpWindowName,
149   _In_ int             X,
150   _In_ int             Y,
151   _In_ int             nWidth,
152   _In_ int             nHeight,
153   _In_opt_ uint64_t    parent)
154 {
155   EnsureWindowClassRegistered();
156   ++sNumWindows;
157
158   HWND hWnd = CreateWindow(DALI_WINDOW_CLASS_NAME.c_str(), lpWindowName, STYLE, X, Y, nWidth + 2 * EDGE_WIDTH, nHeight + 2 * EDGE_HEIGHT, NULL, NULL, GetModuleHandle(NULL), NULL);
159   ::ShowWindow(hWnd, SW_SHOW);
160
161   return reinterpret_cast<uint64_t>(hWnd);
162 }
163
164 void WindowImpl::DestroyHWnd(uint64_t hWnd)
165 {
166   if(hWnd != 0)
167   {
168     ::DestroyWindow(reinterpret_cast<HWND>(hWnd));
169
170     --sNumWindows;
171     EnsureWindowClassUnregistered();
172   }
173 }
174
175 void WindowImpl::SetListener(CallbackBase* callback)
176 {
177   listener = callback;
178 }
179
180 bool WindowImpl::PostWinMessage(
181   _In_ uint32_t Msg,
182   _In_ uint64_t wParam,
183   _In_ uint64_t lParam)
184 {
185   return (bool)PostMessage(reinterpret_cast<HWND>(mHWnd), Msg, wParam, lParam);
186 }
187
188 void WindowImpl::SetHWND(uint64_t inHWnd)
189 {
190   if(mHWnd != inHWnd)
191   {
192     RemoveListener(mHWnd);
193
194     mHWnd      = inHWnd;
195     mHdc       = reinterpret_cast<uint64_t>(GetDC(reinterpret_cast<HWND>(mHWnd)));
196     colorDepth = GetDeviceCaps(reinterpret_cast<HDC>(mHdc), BITSPIXEL) * GetDeviceCaps(reinterpret_cast<HDC>(mHdc), PLANES);
197
198     std::map<uint64_t, WindowImpl*>::iterator x = sHWndToListener.find(mHWnd);
199     if(sHWndToListener.end() == x)
200     {
201       sHWndToListener.insert(std::make_pair(mHWnd, this));
202     }
203     else
204     {
205       x->second = this;
206     }
207   }
208 }
209
210 void WindowImpl::SetWinProc()
211 {
212   // Sets the WinProc function.
213   LONG_PTR ret = SetWindowLongPtr((HWND)mHWnd,
214                                   GWLP_WNDPROC,
215                                   reinterpret_cast<LONG_PTR>(&WinProc));
216
217   if(0 == ret)
218   {
219     DWORD error = GetLastError();
220     return;
221   }
222
223   HMODULE module = GetModuleHandle(nullptr);
224   ret            = SetWindowLongPtr((HWND)mHWnd,
225                          GWLP_HINSTANCE,
226                          reinterpret_cast<LONG_PTR>(&module));
227 }
228
229 bool PostWinThreadMessage(
230   _In_ uint32_t Msg,
231   _In_ uint64_t wParam,
232   _In_ uint64_t lParam,
233   _In_ uint64_t threadID /* = -1*/)
234 {
235   if(-1 == threadID)
236   {
237     threadID = GetCurrentThreadId();
238   }
239
240   return (bool)PostThreadMessage(threadID, Msg, wParam, lParam);
241 }
242
243 struct TTimerCallbackInfo
244 {
245   void*         data;
246   timerCallback callback;
247   HWND          hWnd;
248 };
249
250 void CALLBACK TimerProc(HWND hWnd, UINT nMsg, UINT_PTR nTimerid, DWORD dwTime)
251 {
252   TTimerCallbackInfo* info = (TTimerCallbackInfo*)nTimerid;
253   info->callback(info->data);
254 }
255
256 intptr_t SetTimer(int interval, timerCallback callback, void* data)
257 {
258   HWND hwnd = GetActiveWindow();
259   if(!hwnd)
260   {
261     hwnd = FindWindow(DALI_WINDOW_CLASS_NAME.c_str(), nullptr);
262   }
263
264   if(!hwnd)
265   {
266     return -1;
267   }
268
269   TTimerCallbackInfo* callbackInfo = new TTimerCallbackInfo;
270   callbackInfo->data               = data;
271   callbackInfo->callback           = callback;
272   callbackInfo->hWnd               = hwnd;
273
274   INT_PTR timerID = (INT_PTR)callbackInfo;
275   ::SetTimer(hwnd, timerID, interval, TimerProc);
276
277   return timerID;
278 }
279
280 void KillTimer(intptr_t id)
281 {
282   TTimerCallbackInfo* info = (TTimerCallbackInfo*)id;
283   ::KillTimer(info->hWnd, id);
284   delete info;
285 }
286
287 std::string GetKeyName(int keyCode)
288 {
289   switch(keyCode)
290   {
291     case VK_BACK:
292     {
293       return "Backspace";
294     }
295     case VK_TAB:
296     {
297       return "Tab";
298     }
299     case VK_RETURN:
300     {
301       return "Return";
302     }
303     case VK_ESCAPE:
304     {
305       return "Escape";
306     }
307     case VK_SPACE:
308     {
309       return "Space";
310     }
311     case VK_LEFT:
312     {
313       return "Left";
314     }
315     case VK_UP:
316     {
317       return "Up";
318     }
319     case VK_RIGHT:
320     {
321       return "Right";
322     }
323     case VK_DOWN:
324     {
325       return "Down";
326     }
327     case 48:
328     {
329       return "0";
330     }
331     case 49:
332     {
333       return "1";
334     }
335     case 50:
336     {
337       return "2";
338     }
339     case 51:
340     {
341       return "3";
342     }
343     case 52:
344     {
345       return "4";
346     }
347     case 53:
348     {
349       return "5";
350     }
351     case 54:
352     {
353       return "6";
354     }
355     case 55:
356     {
357       return "7";
358     }
359     case 56:
360     {
361       return "8";
362     }
363     case 57:
364     {
365       return "9";
366     }
367     default:
368     {
369       if(keyCode > 0 && keyCode < 128)
370       {
371         return std::string(1u, static_cast<char>(keyCode));
372       }
373       break;
374     }
375   }
376
377   return "";
378 }
379
380 static LARGE_INTEGER  cpuFrequency;
381 static LARGE_INTEGER* pCpuFrequency = NULL;
382
383 uint64_t GetCurrentThreadId()
384 {
385   return ::GetCurrentThreadId();
386 }
387
388 void GetNanoseconds(uint64_t& timeInNanoseconds)
389 {
390   if(NULL == pCpuFrequency)
391   {
392     pCpuFrequency = &cpuFrequency;
393     QueryPerformanceFrequency(pCpuFrequency);
394   }
395
396   LARGE_INTEGER curTime;
397   QueryPerformanceCounter(&curTime);
398
399   timeInNanoseconds = static_cast<double>(curTime.QuadPart) / static_cast<double>(pCpuFrequency->QuadPart) * 1000000000;
400 }
401
402 unsigned int GetCurrentMilliSeconds(void)
403 {
404   if(NULL == pCpuFrequency)
405   {
406     pCpuFrequency = &cpuFrequency;
407     QueryPerformanceFrequency(pCpuFrequency);
408   }
409
410   LARGE_INTEGER curTime;
411   QueryPerformanceCounter(&curTime);
412
413   return curTime.QuadPart * 1000 / pCpuFrequency->QuadPart;
414 }
415
416 } // namespace WindowsPlatform
417
418 } // namespace Adaptor
419
420 } // namespace Internal
421
422 } // namespace Dali