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