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