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