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