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