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