Tizen 2.1 base
[framework/uifw/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
7 #define WIN32_LEAN_AND_MEAN
8 #include <windows.h>
9 #undef WIN32_LEAN_AND_MEAN
10 #include <windowsx.h>
11
12 #include <Eina.h>
13 #include <Ecore.h>
14 #include <Ecore_Input.h>
15
16 #include "Ecore_Win32.h"
17 #include "ecore_win32_private.h"
18
19 /*============================================================================*
20  *                                  Local                                     *
21  *============================================================================*/
22
23 /**
24  * @cond LOCAL
25  */
26
27 /* OLE IID for Drag'n Drop */
28
29 # define INITGUID
30 # include <basetyps.h>
31 DEFINE_OLEGUID(IID_IEnumFORMATETC, 0x00000103L, 0, 0);
32 DEFINE_OLEGUID(IID_IDataObject,    0x0000010EL, 0, 0);
33 DEFINE_OLEGUID(IID_IDropSource,    0x00000121L, 0, 0);
34 DEFINE_OLEGUID(IID_IDropTarget,    0x00000122L, 0, 0);
35 DEFINE_OLEGUID(IID_IUnknown,       0x00000000L, 0, 0);
36
37 #define IDI_ICON 101
38
39 static int       _ecore_win32_init_count = 0;
40
41 static void
42 _ecore_win32_size_check(Ecore_Win32_Window *win, int w, int h, int *dx, int *dy)
43 {
44    int minimal_width;
45    int minimal_height;
46
47    minimal_width = GetSystemMetrics(SM_CXMIN);
48    minimal_height = GetSystemMetrics(SM_CYMIN);
49    if ((w) < MAX(minimal_width, (int)win->min_width))
50      *dx = 0;
51    if ((w) > (int)win->max_width)
52      *dx = 0;
53    if ((h) < MAX(minimal_height, (int)win->min_height))
54      *dy = 0;
55    if ((h) > (int)win->max_height)
56      *dy = 0;
57 }
58
59 LRESULT CALLBACK
60 _ecore_win32_window_procedure(HWND   window,
61                               UINT   message,
62                               WPARAM window_param,
63                               LPARAM data_param)
64 {
65    Ecore_Win32_Callback_Data *data;
66    POINTS                     point;
67    DWORD                      coord;
68
69    data = (Ecore_Win32_Callback_Data *)malloc(sizeof(Ecore_Win32_Callback_Data));
70    if (!data) return DefWindowProc(window, message, window_param, data_param);
71
72    data->window = window;
73    data->message = message;
74    data->window_param = window_param;
75    data->data_param = data_param;
76    data->timestamp = GetMessageTime();
77    coord = GetMessagePos();
78    point = MAKEPOINTS(coord);
79    data->x = point.x;
80    data->y = point.y;
81    data->discard_ctrl = EINA_FALSE;
82
83    switch (data->message)
84      {
85        /* Keyboard input notifications */
86      case WM_KEYDOWN:
87      case WM_SYSKEYDOWN:
88        if ((data->message == WM_KEYDOWN) &&
89            (data->window_param == VK_CONTROL) &&
90            ((HIWORD(data->data_param) & KF_EXTENDED) == 0))
91          {
92             /* Ctrl left key is pressed */
93             BOOL res;
94             MSG next_msg;
95
96             /*
97              * we check if the next message
98              * - is a WM_KEYDOWN
99              * - has the same timestamp than the Ctrl one
100              * - is the key press of the right Alt key
101              */
102             res = PeekMessage(&next_msg, data->window,
103                               WM_KEYDOWN, WM_KEYDOWN,
104                               PM_NOREMOVE);
105             if (res &&
106                 (next_msg.wParam == VK_MENU) &&
107                 (next_msg.time == data->timestamp) &&
108                 (HIWORD(next_msg.lParam) & KF_EXTENDED))
109               {
110                  INF("discard left Ctrl key press (sent by AltGr key press)");
111                  data->discard_ctrl = EINA_TRUE;
112               }
113          }
114        _ecore_win32_event_handle_key_press(data, 1);
115        return 0;
116      case WM_CHAR:
117      case WM_SYSCHAR:
118        INF("char message");
119        _ecore_win32_event_handle_key_press(data, 0);
120        return 0;
121      case WM_KEYUP:
122      case WM_SYSKEYUP:
123        INF("keyup message");
124        if ((data->window_param == VK_CONTROL) &&
125            ((HIWORD(data->data_param) & KF_EXTENDED) == 0))
126          {
127             /* Ctrl left key is pressed */
128             BOOL res;
129             MSG next_msg;
130
131             /*
132              * we check if the next message
133              * - is a WM_KEYUP or WM_SYSKEYUP
134              * - has the same timestamp than the Ctrl one
135              * - is the key release of the right Alt key
136              */
137             res = PeekMessage(&next_msg, data->window,
138                               WM_KEYUP, WM_SYSKEYUP,
139                               PM_NOREMOVE);
140             if (res &&
141                 ((next_msg.message == WM_KEYUP) ||
142                  (next_msg.message == WM_SYSKEYUP)) &&
143                 (next_msg.wParam == VK_MENU) &&
144                 (next_msg.time == data->timestamp) &&
145                 (HIWORD(next_msg.lParam) & KF_EXTENDED))
146               {
147                  INF("discard left Ctrl key release (sent by AltGr key release)");
148                  data->discard_ctrl = EINA_TRUE;
149               }
150          }
151        _ecore_win32_event_handle_key_release(data);
152        return 0;
153      case WM_SETFOCUS:
154        INF("setfocus message");
155        _ecore_win32_event_handle_focus_in(data);
156        return 0;
157      case WM_KILLFOCUS:
158        INF("kill focus message");
159        _ecore_win32_event_handle_focus_out(data);
160        return 0;
161        /* Mouse input notifications */
162      case WM_LBUTTONDOWN:
163        INF("left button down message");
164        SetCapture(window);
165        _ecore_win32_event_handle_button_press(data, 1);
166        return 0;
167      case WM_MBUTTONDOWN:
168        INF("middle button down message");
169        _ecore_win32_event_handle_button_press(data, 2);
170        return 0;
171      case WM_RBUTTONDOWN:
172        INF("right button down message");
173        _ecore_win32_event_handle_button_press(data, 3);
174        return 0;
175      case WM_LBUTTONUP:
176        {
177           Ecore_Win32_Window *w = NULL;
178
179           INF("left button up message");
180
181           ReleaseCapture();
182           w = (Ecore_Win32_Window *)GetWindowLongPtr(window, GWLP_USERDATA);
183           if (w->drag.dragging)
184             {
185                w->drag.dragging = 0;
186                return 0;
187             }
188
189           _ecore_win32_event_handle_button_release(data, 1);
190           return 0;
191        }
192      case WM_MBUTTONUP:
193        INF("middle button up message");
194        _ecore_win32_event_handle_button_release(data, 2);
195        return 0;
196      case WM_RBUTTONUP:
197        INF("right button up message");
198        _ecore_win32_event_handle_button_release(data, 3);
199        return 0;
200      case WM_MOUSEMOVE:
201        {
202           RECT                rect;
203           Ecore_Win32_Window *w = NULL;
204
205           INF("moue move message");
206
207           w = (Ecore_Win32_Window *)GetWindowLongPtr(window, GWLP_USERDATA);
208
209           if (w->drag.dragging)
210             {
211                POINT pt;
212
213                pt.x = GET_X_LPARAM(data_param);
214                pt.y = GET_Y_LPARAM(data_param);
215                if (ClientToScreen(window, &pt))
216                  {
217                     if (w->drag.type == HTCAPTION)
218                       {
219                          int dx;
220                          int dy;
221
222                          dx = pt.x - w->drag.px;
223                          dy = pt.y - w->drag.py;
224                          ecore_win32_window_move(w, w->drag.x + dx, w->drag.y + dy);
225                          w->drag.x += dx;
226                          w->drag.y += dy;
227                          w->drag.px = pt.x;
228                          w->drag.py = pt.y;
229                          return 0;
230                       }
231                     if (w->drag.type == HTLEFT)
232                       {
233                          int dw;
234
235                          dw = pt.x - w->drag.px;
236                          ecore_win32_window_move_resize(w, w->drag.x + dw, w->drag.y, w->drag.w - dw, w->drag.h);
237                          w->drag.x += dw;
238                          w->drag.w -= dw;
239                          w->drag.px = pt.x;
240                          w->drag.py = pt.y;
241                          return 0;
242                       }
243                     if (w->drag.type == HTRIGHT)
244                       {
245                          int dw;
246
247                          dw = pt.x - w->drag.px;
248                          ecore_win32_window_resize(w, w->drag.w + dw, w->drag.h);
249                          w->drag.w += dw;
250                          w->drag.px = pt.x;
251                          w->drag.py = pt.y;
252                          return 0;
253                       }
254                     if (w->drag.type == HTTOP)
255                       {
256                          int dh;
257
258                          dh = pt.y - w->drag.py;
259                          ecore_win32_window_move_resize(w, w->drag.x, w->drag.y + dh, w->drag.w, w->drag.h - dh);
260                          w->drag.y += dh;
261                          w->drag.h -= dh;
262                          w->drag.px = pt.x;
263                          w->drag.py = pt.y;
264                          return 0;
265                       }
266                     if (w->drag.type == HTBOTTOM)
267                       {
268                          int dh;
269
270                          dh = pt.y - w->drag.py;
271                          ecore_win32_window_resize(w, w->drag.w, w->drag.h + dh);
272                          w->drag.h += dh;
273                          w->drag.px = pt.x;
274                          w->drag.py = pt.y;
275                          return 0;
276                       }
277                     if (w->drag.type == HTTOPLEFT)
278                       {
279                          int dx;
280                          int dy;
281                          int dh;
282                          int dw;
283
284                          dw = pt.x - w->drag.px;
285                          dh = pt.y - w->drag.py;
286                          dx = dw;
287                          dy = dh;
288                          _ecore_win32_size_check(w,
289                                                  w->drag.w - dw, w->drag.h - dh,
290                                                  &dx, &dy);
291
292                          ecore_win32_window_move_resize(w, w->drag.x + dx, w->drag.y + dy, w->drag.w - dw, w->drag.h - dh);
293                          w->drag.x += dx;
294                          w->drag.y += dy;
295                          w->drag.w -= dw;
296                          w->drag.h -= dh;
297                          w->drag.px = pt.x;
298                          w->drag.py = pt.y;
299                          return 0;
300                       }
301                     if (w->drag.type == HTTOPRIGHT)
302                       {
303                          int dx;
304                          int dy;
305                          int dh;
306                          int dw;
307
308                          dw = pt.x - w->drag.px;
309                          dh = pt.y - w->drag.py;
310                          dx = dw;
311                          dy = dh;
312                          _ecore_win32_size_check(w,
313                                                  w->drag.w, w->drag.h - dh,
314                                                  &dx, &dy);
315                          ecore_win32_window_move_resize(w, w->drag.x, w->drag.y + dy, w->drag.w, w->drag.h - dh);
316                          w->drag.y += dy;
317                          w->drag.w += dw;
318                          w->drag.h -= dh;
319                          w->drag.px = pt.x;
320                          w->drag.py = pt.y;
321                          return 0;
322                       }
323                     if (w->drag.type == HTBOTTOMLEFT)
324                       {
325                          int dx;
326                          int dy;
327                          int dh;
328                          int dw;
329
330                          dw = pt.x - w->drag.px;
331                          dh = pt.y - w->drag.py;
332                          dx = dw;
333                          dy = dh;
334                          _ecore_win32_size_check(w,
335                                                  w->drag.w - dw, w->drag.h + dh,
336                                                  &dx, &dy);
337                          ecore_win32_window_move_resize(w, w->drag.x + dx, w->drag.y, w->drag.w - dw, w->drag.h + dh);
338                          w->drag.x += dx;
339                          w->drag.w -= dw;
340                          w->drag.h += dh;
341                          w->drag.px = pt.x;
342                          w->drag.py = pt.y;
343                          return 0;
344                       }
345                     if (w->drag.type == HTBOTTOMRIGHT)
346                       {
347                          int dh;
348                          int dw;
349
350                          dw = pt.x - w->drag.px;
351                          dh = pt.y - w->drag.py;
352                          ecore_win32_window_resize(w, w->drag.w + dw, w->drag.h + dh);
353                          w->drag.w += dw;
354                          w->drag.h += dh;
355                          w->drag.px = pt.x;
356                          w->drag.py = pt.y;
357                          return 0;
358                       }
359                  }
360             }
361
362           if (GetClientRect(window, &rect))
363             {
364                POINT pt;
365
366                INF("mouse in window");
367
368                pt.x = GET_X_LPARAM(data_param);
369                pt.y = GET_Y_LPARAM(data_param);
370                if (!PtInRect(&rect, pt))
371                  {
372                     if (w->pointer_is_in)
373                       {
374                          w->pointer_is_in = 0;
375                          _ecore_win32_event_handle_leave_notify(data);
376                       }
377                  }
378                else
379                  {
380                     if (!w->pointer_is_in)
381                       {
382                          w->pointer_is_in = 1;
383                          _ecore_win32_event_handle_enter_notify(data);
384                       }
385                  }
386             }
387           else
388             {
389                ERR("GetClientRect() failed");
390             }
391           _ecore_win32_event_handle_motion_notify(data);
392
393           return 0;
394        }
395      case WM_MOUSEWHEEL:
396        INF("mouse wheel message");
397        _ecore_win32_event_handle_button_press(data, 4);
398        return 0;
399        /* Window notifications */
400      case WM_CREATE:
401        INF("create window message");
402        _ecore_win32_event_handle_create_notify(data);
403        return 0;
404      case WM_DESTROY:
405        INF("destroy window message");
406        _ecore_win32_event_handle_destroy_notify(data);
407        return 0;
408      case WM_SHOWWINDOW:
409        INF("show window message");
410        if ((data->data_param == SW_OTHERUNZOOM) ||
411            (data->data_param == SW_OTHERZOOM))
412          return 0;
413
414        if (data->window_param)
415          _ecore_win32_event_handle_map_notify(data);
416        else
417          _ecore_win32_event_handle_unmap_notify(data);
418
419        return 0;
420      case WM_CLOSE:
421        INF("close window message");
422        _ecore_win32_event_handle_delete_request(data);
423        return 0;
424      case WM_GETMINMAXINFO:
425        INF("get min max info window message");
426        return TRUE;
427      case WM_MOVING:
428        INF("moving window message");
429        _ecore_win32_event_handle_configure_notify(data);
430        return TRUE;
431      case WM_MOVE:
432        INF("move window message");
433        return 0;
434      case WM_SIZING:
435        INF("sizing window message");
436        _ecore_win32_event_handle_resize(data);
437        _ecore_win32_event_handle_configure_notify(data);
438        return TRUE;
439      case WM_SIZE:
440        INF("size window message");
441        return 0;
442 /*      case WM_WINDOWPOSCHANGING: */
443 /*        { */
444 /*          RECT rect; */
445 /*          GetClientRect(window, &rect); */
446 /*          printf (" *** ecore message : WINDOWPOSCHANGING %ld %ld\n", */
447 /*                  rect.right - rect.left, rect.bottom - rect.top); */
448 /*        } */
449 /*        _ecore_win32_event_handle_configure_notify(data); */
450 /*        return 0; */
451      case WM_WINDOWPOSCHANGED:
452        INF("position changed window message");
453        _ecore_win32_event_handle_configure_notify(data);
454        _ecore_win32_event_handle_expose(data);
455        return 0;
456      case WM_ENTERSIZEMOVE:
457        INF("enter size move window message");
458        return 0;
459      case WM_EXITSIZEMOVE:
460        INF("exit size move window message");
461        return 0;
462      case WM_NCLBUTTONDOWN:
463        INF("non client left button down window message");
464
465        if (((DWORD)window_param == HTCAPTION) ||
466            ((DWORD)window_param == HTBOTTOM) ||
467            ((DWORD)window_param == HTBOTTOMLEFT) ||
468            ((DWORD)window_param == HTBOTTOMRIGHT) ||
469            ((DWORD)window_param == HTLEFT) ||
470            ((DWORD)window_param == HTRIGHT) ||
471            ((DWORD)window_param == HTTOP) ||
472            ((DWORD)window_param == HTTOPLEFT) ||
473            ((DWORD)window_param == HTTOPRIGHT))
474          {
475            Ecore_Win32_Window *w;
476
477            w = (Ecore_Win32_Window *)GetWindowLongPtr(window, GWLP_USERDATA);
478            ecore_win32_window_geometry_get(w,
479                                            NULL, NULL,
480                                            &w->drag.w, &w->drag.h);
481            SetCapture(window);
482            w->drag.type = (DWORD)window_param;
483            w->drag.px = GET_X_LPARAM(data_param);
484            w->drag.py = GET_Y_LPARAM(data_param);
485            w->drag.dragging = 1;
486            return 0;
487          }
488        return DefWindowProc(window, message, window_param, data_param);
489      case WM_SYSCOMMAND:
490        INF("sys command window message %d", (int)window_param);
491
492        if ((((DWORD)window_param & 0xfff0) == SC_MOVE) ||
493            (((DWORD)window_param & 0xfff0) == SC_SIZE))
494          {
495            Ecore_Win32_Window *w;
496
497            INF("sys command MOVE or SIZE window message : %dx%d", GET_X_LPARAM(data_param), GET_Y_LPARAM(data_param));
498
499            w = (Ecore_Win32_Window *)GetWindowLongPtr(window, GWLP_USERDATA);
500            w->drag.dragging = 1;
501            return 0;
502          }
503        return DefWindowProc(window, message, window_param, data_param);
504        /* GDI notifications */
505      case WM_ERASEBKGND:
506        return 1;
507      case WM_PAINT:
508        {
509          RECT rect;
510
511          INF("paint message");
512
513          if (GetUpdateRect(window, &rect, FALSE))
514            {
515               PAINTSTRUCT ps;
516               HDC         hdc;
517
518               hdc = BeginPaint(window, &ps);
519               data->update = rect;
520               _ecore_win32_event_handle_expose(data);
521               EndPaint(window, &ps);
522            }
523          return 0;
524        }
525      case WM_SETREDRAW:
526        INF("set redraw message");
527        return 0;
528      case WM_SYNCPAINT:
529        INF("sync paint message");
530        return 0;
531      default:
532        return DefWindowProc(window, message, window_param, data_param);
533      }
534 }
535
536 /**
537  * @endcond
538  */
539
540
541 /*============================================================================*
542  *                                 Global                                     *
543  *============================================================================*/
544
545
546 HINSTANCE           _ecore_win32_instance = NULL;
547 double              _ecore_win32_double_click_time = 0.25;
548 unsigned long       _ecore_win32_event_last_time = 0;
549 Ecore_Win32_Window *_ecore_win32_event_last_window = NULL;
550 int                 _ecore_win32_log_dom_global = -1;
551
552 int ECORE_WIN32_EVENT_MOUSE_IN              = 0;
553 int ECORE_WIN32_EVENT_MOUSE_OUT             = 0;
554 int ECORE_WIN32_EVENT_WINDOW_FOCUS_IN       = 0;
555 int ECORE_WIN32_EVENT_WINDOW_FOCUS_OUT      = 0;
556 int ECORE_WIN32_EVENT_WINDOW_DAMAGE         = 0;
557 int ECORE_WIN32_EVENT_WINDOW_CREATE         = 0;
558 int ECORE_WIN32_EVENT_WINDOW_DESTROY        = 0;
559 int ECORE_WIN32_EVENT_WINDOW_SHOW           = 0;
560 int ECORE_WIN32_EVENT_WINDOW_HIDE           = 0;
561 int ECORE_WIN32_EVENT_WINDOW_CONFIGURE      = 0;
562 int ECORE_WIN32_EVENT_WINDOW_RESIZE         = 0;
563 int ECORE_WIN32_EVENT_WINDOW_DELETE_REQUEST = 0;
564
565 /*============================================================================*
566  *                                   API                                      *
567  *============================================================================*/
568
569 /**
570  * @addtogroup Ecore_Win32_Group Ecore_Win32 library
571  *
572  * Ecore_Win32 is a library that wraps Windows graphic functions
573  * and integrate them nicely into the Ecore main loop.
574  *
575  * @section Ecore_Win32_Sec_Init Initialisation / Shutdown
576  *
577  * To fill...
578  *
579  * @section Ecore_Win32_Sec_Icons How to set icons to an application
580  *
581  * It is possible to also sets the icon of the application easily:
582  *
583  * @li Create an icon with your favorite image creator. The Gimp is a
584  * good choice. Create several images of size 16, 32 and 48. You can
585  * also create images of size 24, 64, 128 and 256. Paste all of them
586  * in the image of size 16 as a layer. Save the image of size 16 with
587  * the name my_icon.ico. Put it where the source code of the
588  * application is located.
589  * @li Create my_icon_rc.rc file with your code editor and add in it:
590  * @code
591  * 101 ICON DISCARDABLE "my_icon.ico"
592  * @endcode
593  * @li With Visual Studio, put that file in the 'Resource file' part
594  * of the project.
595  * @li With MinGW, you have to compile it with windres:
596  * @code
597  * windres my_icon_rc.rc my_icon_rc.o
598  * @endcode
599  * and add my_icon_rc.o to the object files of the application.
600  *
601  * @note The value 101 must not be changed, it's the ID used
602  * internally by Ecore_Win32 to get the icons.
603  *
604  * @{
605  */
606
607 /**
608  * @brief Initialize the Ecore_Win32 library.
609  *
610  * @return 1 or greater on success, 0 on error.
611  *
612  * This function sets up the Windows graphic system. It returns 0 on
613  * failure, otherwise it returns the number of times it has already been
614  * called.
615  *
616  * When Ecore_Win32 is not used anymore, call ecore_win32_shutdown()
617  * to shut down the Ecore_Win32 library.
618  */
619 EAPI int
620 ecore_win32_init()
621 {
622    WNDCLASSEX wc;
623    HICON      icon;
624    HICON      icon_sm;
625
626    if (++_ecore_win32_init_count != 1)
627      return _ecore_win32_init_count;
628
629    if (!eina_init())
630      return --_ecore_win32_init_count;
631
632    _ecore_win32_log_dom_global = eina_log_domain_register
633      ("ecore_win32", ECORE_WIN32_DEFAULT_LOG_COLOR);
634    if (_ecore_win32_log_dom_global < 0)
635      {
636         EINA_LOG_ERR("Ecore_Win32: Could not register log domain");
637         goto shutdown_eina;
638      }
639
640    if (!ecore_event_init())
641      {
642         ERR("Ecore_Win32: Could not init ecore_event");
643         goto unregister_log_domain;
644      }
645
646    _ecore_win32_instance = GetModuleHandle(NULL);
647    if (!_ecore_win32_instance)
648      {
649         ERR("GetModuleHandle() failed");
650         goto shutdown_ecore_event;
651      }
652
653    icon = LoadImage(_ecore_win32_instance,
654                     MAKEINTRESOURCE(IDI_ICON),
655                     IMAGE_ICON,
656                     GetSystemMetrics(SM_CXICON),
657                     GetSystemMetrics(SM_CYICON),
658                     LR_DEFAULTCOLOR);
659    icon_sm = LoadImage(_ecore_win32_instance,
660                        MAKEINTRESOURCE(IDI_ICON),
661                        IMAGE_ICON,
662                        GetSystemMetrics(SM_CXSMICON),
663                        GetSystemMetrics(SM_CYSMICON),
664                        LR_DEFAULTCOLOR);
665    if (!icon)
666      icon = LoadIcon (NULL, IDI_APPLICATION);
667    if (!icon_sm)
668      icon_sm = LoadIcon (NULL, IDI_APPLICATION);
669
670    memset (&wc, 0, sizeof (WNDCLASSEX));
671    wc.cbSize = sizeof (WNDCLASSEX);
672    wc.style = CS_HREDRAW | CS_VREDRAW;
673    wc.lpfnWndProc = _ecore_win32_window_procedure;
674    wc.cbClsExtra = 0;
675    wc.cbWndExtra = 0;
676    wc.hInstance = _ecore_win32_instance;
677    wc.hIcon = icon;
678    wc.hCursor = LoadCursor (NULL, IDC_ARROW);
679    wc.hbrBackground = (HBRUSH)(1 + COLOR_BTNFACE);
680    wc.lpszMenuName =  NULL;
681    wc.lpszClassName = ECORE_WIN32_WINDOW_CLASS;
682    wc.hIconSm = icon_sm;
683
684    if(!RegisterClassEx(&wc))
685      {
686         ERR("RegisterClass() failed");
687         goto free_library;
688      }
689
690    if (!ecore_win32_dnd_init())
691      {
692         ERR("ecore_win32_dnd_init() failed");
693         goto unregister_class;
694      }
695
696    if (!ECORE_WIN32_EVENT_MOUSE_IN)
697      {
698         ECORE_WIN32_EVENT_MOUSE_IN              = ecore_event_type_new();
699         ECORE_WIN32_EVENT_MOUSE_OUT             = ecore_event_type_new();
700         ECORE_WIN32_EVENT_WINDOW_FOCUS_IN       = ecore_event_type_new();
701         ECORE_WIN32_EVENT_WINDOW_FOCUS_OUT      = ecore_event_type_new();
702         ECORE_WIN32_EVENT_WINDOW_DAMAGE         = ecore_event_type_new();
703         ECORE_WIN32_EVENT_WINDOW_CREATE         = ecore_event_type_new();
704         ECORE_WIN32_EVENT_WINDOW_DESTROY        = ecore_event_type_new();
705         ECORE_WIN32_EVENT_WINDOW_SHOW           = ecore_event_type_new();
706         ECORE_WIN32_EVENT_WINDOW_HIDE           = ecore_event_type_new();
707         ECORE_WIN32_EVENT_WINDOW_CONFIGURE      = ecore_event_type_new();
708         ECORE_WIN32_EVENT_WINDOW_RESIZE         = ecore_event_type_new();
709         ECORE_WIN32_EVENT_WINDOW_DELETE_REQUEST = ecore_event_type_new();
710      }
711
712    return _ecore_win32_init_count;
713
714  unregister_class:
715    UnregisterClass(ECORE_WIN32_WINDOW_CLASS, _ecore_win32_instance);
716  free_library:
717    FreeLibrary(_ecore_win32_instance);
718  shutdown_ecore_event:
719    ecore_event_shutdown();
720  unregister_log_domain:
721    eina_log_domain_unregister(_ecore_win32_log_dom_global);
722  shutdown_eina:
723    eina_shutdown();
724
725    return --_ecore_win32_init_count;
726 }
727
728 /**
729  * @brief Shut down the Ecore_Win32 library.
730  *
731  * @return 0 when the library is completely shut down, 1 or
732  * greater otherwise.
733  *
734  * This function shuts down the Ecore_Win32 library. It returns 0 when it has
735  * been called the same number of times than ecore_win32_init(). In that case
736  * it shuts down all the Windows graphic system.
737  */
738 EAPI int
739 ecore_win32_shutdown()
740 {
741    if (--_ecore_win32_init_count != 0)
742      return _ecore_win32_init_count;
743
744    ecore_win32_dnd_shutdown();
745
746    if (!UnregisterClass(ECORE_WIN32_WINDOW_CLASS, _ecore_win32_instance))
747      INF("UnregisterClass() failed");
748
749    if (!FreeLibrary(_ecore_win32_instance))
750      INF("FreeLibrary() failed");
751
752    _ecore_win32_instance = NULL;
753
754    ecore_event_shutdown();
755    eina_log_domain_unregister(_ecore_win32_log_dom_global);
756    _ecore_win32_log_dom_global = -1;
757    eina_shutdown();
758
759    return _ecore_win32_init_count;
760 }
761
762 /**
763  * @brief Retrieve the depth of the screen.
764  *
765  * @return The depth of the screen.
766  *
767  * This function returns the depth of the screen. If an error occurs,
768  * it returns 0.
769  */
770 EAPI int
771 ecore_win32_screen_depth_get()
772 {
773    HDC dc;
774    int depth;
775
776    INF("getting screen depth");
777
778    dc = GetDC(NULL);
779    if (!dc)
780      {
781         ERR("GetDC() failed");
782         return 0;
783      }
784
785    depth = GetDeviceCaps(dc, BITSPIXEL);
786    if (!ReleaseDC(NULL, dc))
787      {
788         ERR("ReleaseDC() failed (device context not released)");
789      }
790
791    return depth;
792 }
793
794 /**
795  * @brief Sets the timeout for a double and triple clicks to be flagged.
796  *
797  * @param t The time in seconds.
798  *
799  * This function sets the time @p t between clicks before the
800  * double_click flag is set in a button down event. If 3 clicks occur
801  * within double this time, the triple_click flag is also set.
802  */
803 EAPI void
804 ecore_win32_double_click_time_set(double t)
805 {
806    if (t < 0.0) t = 0.0;
807    _ecore_win32_double_click_time = t;
808 }
809
810 /**
811  * @brief Retrieve the double and triple click flag timeout.
812  *
813  * @return The timeout for double clicks in seconds.
814  *
815  * This function returns the double clicks in seconds. If
816  * ecore_win32_double_click_time_set() has not been called, the
817  * default value is returned. See ecore_win32_double_click_time_set()
818  * for more informations.
819  */
820 EAPI double
821 ecore_win32_double_click_time_get(void)
822 {
823    return _ecore_win32_double_click_time;
824 }
825
826 /**
827  * @brief Return the last event time.
828  *
829  * @return The last envent time.
830  *
831  * This function returns the last event time.
832  */
833 EAPI unsigned long
834 ecore_win32_current_time_get(void)
835 {
836    return _ecore_win32_event_last_time;
837 }
838
839 /**
840  * @}
841  */