[ecore] merged svn latest code (svn54830)
[profile/ivi/ecore.git] / src / lib / ecore_win32 / ecore_win32.c
1 #ifdef HAVE_CONFIG_H
2 # include <config.h>
3 #endif
4
5 #include <stdlib.h>
6 #include <stdio.h>   /* for printf */
7
8 #define WIN32_LEAN_AND_MEAN
9 #include <windows.h>
10 #undef WIN32_LEAN_AND_MEAN
11 #include <windowsx.h>
12
13 #include <Eina.h>
14 #include <Ecore.h>
15 #include <Ecore_Input.h>
16
17 #include "Ecore_Win32.h"
18 #include "ecore_win32_private.h"
19
20 /*============================================================================*
21  *                                  Local                                     *
22  *============================================================================*/
23
24 /**
25  * @cond LOCAL
26  */
27
28 /* OLE IID for Drag'n Drop */
29
30 # define INITGUID
31 # include <basetyps.h>
32 DEFINE_OLEGUID(IID_IEnumFORMATETC, 0x00000103L, 0, 0);
33 DEFINE_OLEGUID(IID_IDataObject,    0x0000010EL, 0, 0);
34 DEFINE_OLEGUID(IID_IDropSource,    0x00000121L, 0, 0);
35 DEFINE_OLEGUID(IID_IDropTarget,    0x00000122L, 0, 0);
36 DEFINE_OLEGUID(IID_IUnknown,       0x00000000L, 0, 0);
37
38 static int       _ecore_win32_init_count = 0;
39
40 LRESULT CALLBACK
41 _ecore_win32_window_procedure(HWND   window,
42                               UINT   message,
43                               WPARAM window_param,
44                               LPARAM data_param)
45 {
46    Ecore_Win32_Callback_Data *data;
47    POINTS                     pt;
48    DWORD                      coord;
49
50    data = (Ecore_Win32_Callback_Data *)malloc(sizeof(Ecore_Win32_Callback_Data));
51    if (!data) return DefWindowProc(window, message, window_param, data_param);
52
53    data->window = window;
54    data->message = message;
55    data->window_param = window_param;
56    data->data_param = data_param;
57    data->time = GetMessageTime();
58    coord = GetMessagePos();
59    pt = MAKEPOINTS(coord);
60    data->x = pt.x;
61    data->y = pt.y;
62
63    switch (data->message)
64      {
65        /* Keyboard input notifications */
66      case WM_KEYDOWN:
67        _ecore_win32_event_handle_key_press(data, 1);
68        return 0;
69      case WM_CHAR:
70        _ecore_win32_event_handle_key_press(data, 0);
71        return 0;
72      case WM_KEYUP:
73        _ecore_win32_event_handle_key_release(data, 1);
74        return 0;
75      case WM_SETFOCUS:
76        _ecore_win32_event_handle_focus_in(data);
77        return 0;
78      case WM_KILLFOCUS:
79        _ecore_win32_event_handle_focus_out(data);
80        return 0;
81        /* Mouse input notifications */
82      case WM_LBUTTONDOWN:
83        _ecore_win32_event_handle_button_press(data, 1);
84        return 0;
85      case WM_MBUTTONDOWN:
86        _ecore_win32_event_handle_button_press(data, 2);
87        return 0;
88      case WM_RBUTTONDOWN:
89        _ecore_win32_event_handle_button_press(data, 3);
90        return 0;
91      case WM_LBUTTONUP:
92        _ecore_win32_event_handle_button_release(data, 1);
93        return 0;
94      case WM_MBUTTONUP:
95        _ecore_win32_event_handle_button_release(data, 2);
96        return 0;
97      case WM_RBUTTONUP:
98        _ecore_win32_event_handle_button_release(data, 3);
99        return 0;
100      case WM_MOUSEMOVE:
101        {
102           RECT                        rect;
103           struct _Ecore_Win32_Window *w = NULL;
104
105           w = (struct _Ecore_Win32_Window *)GetWindowLong(window, GWL_USERDATA);
106
107           if (GetClientRect(window, &rect))
108             {
109                POINT pt;
110
111                INF("mouse in window");
112
113                pt.x = GET_X_LPARAM(data_param);
114                pt.y = GET_Y_LPARAM(data_param);
115                if (!PtInRect(&rect, pt))
116                  {
117                     if (w->pointer_is_in)
118                       {
119                          w->pointer_is_in = 0;
120                          _ecore_win32_event_handle_leave_notify(data);
121                       }
122                  }
123                else
124                  {
125                     if (!w->pointer_is_in)
126                       {
127                          w->pointer_is_in = 1;
128                          _ecore_win32_event_handle_enter_notify(data);
129                       }
130                  }
131             }
132           else
133             {
134                ERR("GetClientRect() failed");
135             }
136           _ecore_win32_event_handle_motion_notify(data);
137
138           return 0;
139        }
140      case WM_MOUSEWHEEL:
141        _ecore_win32_event_handle_button_press(data, 4);
142        return 0;
143        /* Window notifications */
144      case WM_CREATE:
145        _ecore_win32_event_handle_create_notify(data);
146        return 0;
147      case WM_DESTROY:
148        _ecore_win32_event_handle_destroy_notify(data);
149        return 0;
150      case WM_SHOWWINDOW:
151        if ((data->data_param == SW_OTHERUNZOOM) ||
152            (data->data_param == SW_OTHERZOOM))
153          return 0;
154
155        if (data->window_param)
156          _ecore_win32_event_handle_map_notify(data);
157        else
158          _ecore_win32_event_handle_unmap_notify(data);
159
160        return 0;
161      case WM_CLOSE:
162        _ecore_win32_event_handle_delete_request(data);
163        return 0;
164      case WM_MOVING:
165        printf (" * ecore message : moving\n");
166        return TRUE;
167      case WM_MOVE:
168        printf (" * ecore message : moved\n");
169        return 0;
170      case WM_SIZING:
171        printf (" * ecore message : sizing\n");
172        _ecore_win32_event_handle_resize(data);
173        _ecore_win32_event_handle_configure_notify(data);
174        return TRUE;
175      case WM_SIZE:
176        printf (" * ecore message : sized\n");
177        return 0;
178 /*      case WM_WINDOWPOSCHANGING: */
179 /*        { */
180 /*          RECT rect; */
181 /*          GetClientRect(window, &rect); */
182 /*          printf (" *** ecore message : WINDOWPOSCHANGING %ld %ld\n", */
183 /*                  rect.right - rect.left, rect.bottom - rect.top); */
184 /*        } */
185 /*        _ecore_win32_event_handle_configure_notify(data); */
186 /*        return 0; */
187      case WM_WINDOWPOSCHANGED:
188        _ecore_win32_event_handle_configure_notify(data);
189        return 0;
190      case WM_ENTERSIZEMOVE :
191        printf (" * ecore message : WM_ENTERSIZEMOVE \n");
192        return 0;
193      case WM_EXITSIZEMOVE:
194        printf (" * ecore message : WM_EXITSIZEMOVE\n");
195        return 0;
196        /* GDI notifications */
197      case WM_PAINT:
198        {
199          RECT rect;
200
201          if (GetUpdateRect(window, &rect, FALSE))
202            {
203               PAINTSTRUCT ps;
204               HDC         hdc;
205
206               hdc = BeginPaint(window, &ps);
207               data->update = rect;
208               _ecore_win32_event_handle_expose(data);
209               EndPaint(window, &ps);
210            }
211          return 0;
212        }
213      case WM_SETREDRAW:
214        printf (" * ecore message : WM_SETREDRAW\n");
215        return 0;
216      case WM_SYNCPAINT:
217        printf (" * ecore message : WM_SYNCPAINT\n");
218        return 0;
219      default:
220        return DefWindowProc(window, message, window_param, data_param);
221      }
222 }
223
224 /**
225  * @endcond
226  */
227
228
229 /*============================================================================*
230  *                                 Global                                     *
231  *============================================================================*/
232
233
234 HINSTANCE           _ecore_win32_instance = NULL;
235 double              _ecore_win32_double_click_time = 0.25;
236 long                _ecore_win32_event_last_time = 0;
237 Ecore_Win32_Window *_ecore_win32_event_last_window = NULL;
238 int                 _ecore_win32_log_dom_global = -1;
239
240 int ECORE_WIN32_EVENT_MOUSE_IN              = 0;
241 int ECORE_WIN32_EVENT_MOUSE_OUT             = 0;
242 int ECORE_WIN32_EVENT_WINDOW_FOCUS_IN       = 0;
243 int ECORE_WIN32_EVENT_WINDOW_FOCUS_OUT      = 0;
244 int ECORE_WIN32_EVENT_WINDOW_DAMAGE         = 0;
245 int ECORE_WIN32_EVENT_WINDOW_CREATE         = 0;
246 int ECORE_WIN32_EVENT_WINDOW_DESTROY        = 0;
247 int ECORE_WIN32_EVENT_WINDOW_SHOW           = 0;
248 int ECORE_WIN32_EVENT_WINDOW_HIDE           = 0;
249 int ECORE_WIN32_EVENT_WINDOW_CONFIGURE      = 0;
250 int ECORE_WIN32_EVENT_WINDOW_RESIZE         = 0;
251 int ECORE_WIN32_EVENT_WINDOW_DELETE_REQUEST = 0;
252
253 /*============================================================================*
254  *                                   API                                      *
255  *============================================================================*/
256
257 /**
258  * @addtogroup Ecore_Win32_Group Ecore_Win32 library
259  *
260  * Ecore_Win32 is a library that wraps Windows graphic functions
261  * and integrate them nicely into the Ecore main loop.
262  *
263  * @{
264  */
265
266 /**
267  * @brief Initialize the Ecore_Win32 library.
268  *
269  * @return 1 or greater on success, 0 on error.
270  *
271  * This function sets up the Windows graphic system. It returns 0 on
272  * failure, otherwise it returns the number of times it has already been
273  * called.
274  *
275  * When Ecore_Win32 is not used anymore, call ecore_win32_shutdown()
276  * to shut down the Ecore_Win32 library.
277  */
278 EAPI int
279 ecore_win32_init()
280 {
281    WNDCLASS wc;
282
283    if (++_ecore_win32_init_count != 1)
284      return _ecore_win32_init_count;
285
286    if (!eina_init())
287      return --_ecore_win32_init_count;
288
289    _ecore_win32_log_dom_global = eina_log_domain_register
290      ("ecore_win32", ECORE_WIN32_DEFAULT_LOG_COLOR);
291    if (_ecore_win32_log_dom_global < 0)
292      {
293         EINA_LOG_ERR("Ecore_Win32: Could not register log domain");
294         goto shutdown_eina;
295      }
296
297    if (!ecore_event_init())
298      {
299         ERR("Ecore_Win32: Could not init ecore_event");
300         goto unregister_log_domain;
301      }
302
303    _ecore_win32_instance = GetModuleHandle(NULL);
304    if (!_ecore_win32_instance)
305      {
306         ERR("GetModuleHandle() failed");
307         goto shutdown_ecore_event;
308      }
309
310    memset (&wc, 0, sizeof (WNDCLASS));
311    wc.style = CS_HREDRAW | CS_VREDRAW;
312    wc.lpfnWndProc = _ecore_win32_window_procedure;
313    wc.cbClsExtra = 0;
314    wc.cbWndExtra = 0;
315    wc.hInstance = _ecore_win32_instance;
316    wc.hIcon = LoadIcon (NULL, IDI_APPLICATION);
317    wc.hCursor = LoadCursor (NULL, IDC_ARROW);
318    wc.hbrBackground = (HBRUSH)(1 + COLOR_BTNFACE);
319    wc.lpszMenuName =  NULL;
320    wc.lpszClassName = ECORE_WIN32_WINDOW_CLASS;
321
322    if(!RegisterClass(&wc))
323      {
324         ERR("RegisterClass() failed");
325         goto free_library;
326      }
327
328    if (!ecore_win32_dnd_init())
329      {
330         ERR("ecore_win32_dnd_init() failed");
331         goto unregister_class;
332      }
333
334    if (!ECORE_WIN32_EVENT_MOUSE_IN)
335      {
336         ECORE_WIN32_EVENT_MOUSE_IN              = ecore_event_type_new();
337         ECORE_WIN32_EVENT_MOUSE_OUT             = ecore_event_type_new();
338         ECORE_WIN32_EVENT_WINDOW_FOCUS_IN       = ecore_event_type_new();
339         ECORE_WIN32_EVENT_WINDOW_FOCUS_OUT      = ecore_event_type_new();
340         ECORE_WIN32_EVENT_WINDOW_DAMAGE         = ecore_event_type_new();
341         ECORE_WIN32_EVENT_WINDOW_CREATE         = ecore_event_type_new();
342         ECORE_WIN32_EVENT_WINDOW_DESTROY        = ecore_event_type_new();
343         ECORE_WIN32_EVENT_WINDOW_SHOW           = ecore_event_type_new();
344         ECORE_WIN32_EVENT_WINDOW_HIDE           = ecore_event_type_new();
345         ECORE_WIN32_EVENT_WINDOW_CONFIGURE      = ecore_event_type_new();
346         ECORE_WIN32_EVENT_WINDOW_RESIZE         = ecore_event_type_new();
347         ECORE_WIN32_EVENT_WINDOW_DELETE_REQUEST = ecore_event_type_new();
348      }
349
350    return _ecore_win32_init_count;
351
352  unregister_class:
353    UnregisterClass(ECORE_WIN32_WINDOW_CLASS, _ecore_win32_instance);
354  free_library:
355    FreeLibrary(_ecore_win32_instance);
356  shutdown_ecore_event:
357    ecore_event_shutdown();
358  unregister_log_domain:
359    eina_log_domain_unregister(_ecore_win32_log_dom_global);
360  shutdown_eina:
361    eina_shutdown();
362
363    return --_ecore_win32_init_count;
364 }
365
366 /**
367  * @brief Shut down the Ecore_Win32 library.
368  *
369  * @return 0 when the library is completely shut down, 1 or
370  * greater otherwise.
371  *
372  * This function shuts down the Ecore_Win32 library. It returns 0 when it has
373  * been called the same number of times than ecore_win32_init(). In that case
374  * it shuts down all the Windows graphic system.
375  */
376 EAPI int
377 ecore_win32_shutdown()
378 {
379    if (--_ecore_win32_init_count != 0)
380      return _ecore_win32_init_count;
381
382    ecore_win32_dnd_shutdown();
383
384    if (!UnregisterClass(ECORE_WIN32_WINDOW_CLASS, _ecore_win32_instance))
385      INF("UnregisterClass() failed");
386
387    if (!FreeLibrary(_ecore_win32_instance))
388      INF("FreeLibrary() failed");
389
390    _ecore_win32_instance = NULL;
391
392    ecore_event_shutdown();
393    eina_log_domain_unregister(_ecore_win32_log_dom_global);
394    _ecore_win32_log_dom_global = -1;
395    eina_shutdown();
396
397    return _ecore_win32_init_count;
398 }
399
400 /**
401  * @brief Retrieve the depth of the screen.
402  *
403  * @return The depth of the screen.
404  *
405  * This function returns the depth of the screen. If an error occurs,
406  * it returns 0.
407  */
408 EAPI int
409 ecore_win32_screen_depth_get()
410 {
411    HDC dc;
412    int depth;
413
414    INF("getting screen depth");
415
416    dc = GetDC(NULL);
417    if (!dc)
418      {
419         ERR("GetDC() failed");
420         return 0;
421      }
422
423    depth = GetDeviceCaps(dc, BITSPIXEL);
424    if (!ReleaseDC(NULL, dc))
425      {
426         ERR("ReleaseDC() failed (device context not released)");
427      }
428
429    return depth;
430 }
431
432 /**
433  * @brief Sets the timeout for a double and triple clicks to be flagged.
434  *
435  * @param t The time in seconds.
436  *
437  * This function sets the time @p t between clicks before the
438  * double_click flag is set in a button down event. If 3 clicks occur
439  * within double this time, the triple_click flag is also set.
440  */
441 EAPI void
442 ecore_win32_double_click_time_set(double t)
443 {
444    if (t < 0.0) t = 0.0;
445    _ecore_win32_double_click_time = t;
446 }
447
448 /**
449  * @brief Retrieve the double and triple click flag timeout.
450  *
451  * @return The timeout for double clicks in seconds.
452  *
453  * This function returns the double clicks in seconds. If
454  * ecore_win32_double_click_time_set() has not been called, the
455  * default value is returned. See ecore_win32_double_click_time_set()
456  * for more informations.
457  */
458 EAPI double
459 ecore_win32_double_click_time_get(void)
460 {
461    return _ecore_win32_double_click_time;
462 }
463
464 /**
465  * @brief Return the last event time.
466  *
467  * @return The last envent time.
468  *
469  * This function returns the last event time.
470  */
471 EAPI long
472 ecore_win32_current_time_get(void)
473 {
474    return _ecore_win32_event_last_time;
475 }
476
477 /**
478  * @}
479  */