7 #define WIN32_LEAN_AND_MEAN
9 #undef WIN32_LEAN_AND_MEAN
14 #include <Ecore_Input.h>
16 #include "Ecore_Win32.h"
17 #include "ecore_win32_private.h"
19 /*============================================================================*
21 *============================================================================*/
27 /* OLE IID for Drag'n Drop */
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);
39 static int _ecore_win32_init_count = 0;
42 _ecore_win32_size_check(Ecore_Win32_Window *win, int w, int h, int *dx, int *dy)
47 minimal_width = GetSystemMetrics(SM_CXMIN);
48 minimal_height = GetSystemMetrics(SM_CYMIN);
49 if ((w) < MAX(minimal_width, (int)win->min_width))
51 if ((w) > (int)win->max_width)
53 if ((h) < MAX(minimal_height, (int)win->min_height))
55 if ((h) > (int)win->max_height)
60 _ecore_win32_window_procedure(HWND window,
65 Ecore_Win32_Callback_Data *data;
69 data = (Ecore_Win32_Callback_Data *)malloc(sizeof(Ecore_Win32_Callback_Data));
70 if (!data) return DefWindowProc(window, message, window_param, data_param);
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);
82 switch (data->message)
84 /* Keyboard input notifications */
86 INF("keydown message");
87 _ecore_win32_event_handle_key_press(data, 1);
90 /* INF("char message"); */
91 /* _ecore_win32_event_handle_key_press(data, 0); */
95 _ecore_win32_event_handle_key_release(data, 1);
98 INF("setfocus message");
99 _ecore_win32_event_handle_focus_in(data);
102 INF("kill focus message");
103 _ecore_win32_event_handle_focus_out(data);
105 /* Mouse input notifications */
107 INF("left button down message");
108 _ecore_win32_event_handle_button_press(data, 1);
111 INF("middle button down message");
112 _ecore_win32_event_handle_button_press(data, 2);
115 INF("right button down message");
116 _ecore_win32_event_handle_button_press(data, 3);
120 Ecore_Win32_Window *w = NULL;
122 INF("left button up message");
124 w = (Ecore_Win32_Window *)GetWindowLongPtr(window, GWLP_USERDATA);
125 if (w->drag.dragging)
128 w->drag.dragging = 0;
132 _ecore_win32_event_handle_button_release(data, 1);
136 INF("middle button up message");
137 _ecore_win32_event_handle_button_release(data, 2);
140 INF("right button up message");
141 _ecore_win32_event_handle_button_release(data, 3);
146 Ecore_Win32_Window *w = NULL;
148 INF("moue move message");
150 w = (Ecore_Win32_Window *)GetWindowLongPtr(window, GWLP_USERDATA);
152 if (w->drag.dragging)
156 pt.x = GET_X_LPARAM(data_param);
157 pt.y = GET_Y_LPARAM(data_param);
158 if (ClientToScreen(window, &pt))
160 if (w->drag.type == HTCAPTION)
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);
174 if (w->drag.type == HTLEFT)
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);
186 if (w->drag.type == HTRIGHT)
190 dw = pt.x - w->drag.px;
191 ecore_win32_window_resize(w, w->drag.w + dw, w->drag.h);
197 if (w->drag.type == HTTOP)
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);
209 if (w->drag.type == HTBOTTOM)
213 dh = pt.y - w->drag.py;
214 ecore_win32_window_resize(w, w->drag.w, w->drag.h + dh);
220 if (w->drag.type == HTTOPLEFT)
227 dw = pt.x - w->drag.px;
228 dh = pt.y - w->drag.py;
231 _ecore_win32_size_check(w,
232 w->drag.w - dw, w->drag.h - dh,
235 ecore_win32_window_move_resize(w, w->drag.x + dx, w->drag.y + dy, w->drag.w - dw, w->drag.h - dh);
244 if (w->drag.type == HTTOPRIGHT)
251 dw = pt.x - w->drag.px;
252 dh = pt.y - w->drag.py;
255 _ecore_win32_size_check(w,
256 w->drag.w, w->drag.h - dh,
258 ecore_win32_window_move_resize(w, w->drag.x, w->drag.y + dy, w->drag.w, w->drag.h - dh);
266 if (w->drag.type == HTBOTTOMLEFT)
273 dw = pt.x - w->drag.px;
274 dh = pt.y - w->drag.py;
277 _ecore_win32_size_check(w,
278 w->drag.w - dw, w->drag.h + dh,
280 ecore_win32_window_move_resize(w, w->drag.x + dx, w->drag.y, w->drag.w - dw, w->drag.h + dh);
288 if (w->drag.type == HTBOTTOMRIGHT)
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);
305 if (GetClientRect(window, &rect))
309 INF("mouse in window");
311 pt.x = GET_X_LPARAM(data_param);
312 pt.y = GET_Y_LPARAM(data_param);
313 if (!PtInRect(&rect, pt))
315 if (w->pointer_is_in)
317 w->pointer_is_in = 0;
318 _ecore_win32_event_handle_leave_notify(data);
323 if (!w->pointer_is_in)
325 w->pointer_is_in = 1;
326 _ecore_win32_event_handle_enter_notify(data);
332 ERR("GetClientRect() failed");
334 _ecore_win32_event_handle_motion_notify(data);
339 INF("mouse wheel message");
340 _ecore_win32_event_handle_button_press(data, 4);
342 /* Window notifications */
344 INF("create window message");
345 _ecore_win32_event_handle_create_notify(data);
348 INF("destroy window message");
349 _ecore_win32_event_handle_destroy_notify(data);
352 INF("show window message");
353 if ((data->data_param == SW_OTHERUNZOOM) ||
354 (data->data_param == SW_OTHERZOOM))
357 if (data->window_param)
358 _ecore_win32_event_handle_map_notify(data);
360 _ecore_win32_event_handle_unmap_notify(data);
364 INF("close window message");
365 _ecore_win32_event_handle_delete_request(data);
367 case WM_GETMINMAXINFO:
368 INF("get min max info window message");
371 INF("moving window message");
372 _ecore_win32_event_handle_configure_notify(data);
375 INF("move window message");
378 INF("sizing window message");
379 _ecore_win32_event_handle_resize(data);
380 _ecore_win32_event_handle_configure_notify(data);
383 INF("size window message");
385 /* case WM_WINDOWPOSCHANGING: */
388 /* GetClientRect(window, &rect); */
389 /* printf (" *** ecore message : WINDOWPOSCHANGING %ld %ld\n", */
390 /* rect.right - rect.left, rect.bottom - rect.top); */
392 /* _ecore_win32_event_handle_configure_notify(data); */
394 case WM_WINDOWPOSCHANGED:
395 INF("position changed window message");
396 _ecore_win32_event_handle_configure_notify(data);
398 case WM_ENTERSIZEMOVE:
399 INF("enter size move window message");
401 case WM_EXITSIZEMOVE:
402 INF("exit size move window message");
404 case WM_NCLBUTTONDOWN:
405 INF("non client left button down window message");
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))
417 Ecore_Win32_Window *w;
419 w = (Ecore_Win32_Window *)GetWindowLongPtr(window, GWLP_USERDATA);
420 ecore_win32_window_geometry_get(w,
422 &w->drag.w, &w->drag.h);
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;
430 return DefWindowProc(window, message, window_param, data_param);
432 INF("sys command window message %d", (int)window_param);
434 if ((((DWORD)window_param & 0xfff0) == SC_MOVE) ||
435 (((DWORD)window_param & 0xfff0) == SC_SIZE))
437 Ecore_Win32_Window *w;
439 INF("sys command MOVE or SIZE window message : %dx%d", GET_X_LPARAM(data_param), GET_Y_LPARAM(data_param));
441 w = (Ecore_Win32_Window *)GetWindowLongPtr(window, GWLP_USERDATA);
442 w->drag.dragging = 1;
445 return DefWindowProc(window, message, window_param, data_param);
446 /* GDI notifications */
453 INF("paint message");
455 if (GetUpdateRect(window, &rect, FALSE))
460 hdc = BeginPaint(window, &ps);
462 _ecore_win32_event_handle_expose(data);
463 EndPaint(window, &ps);
468 INF("set redraw message");
471 INF("sync paint message");
474 return DefWindowProc(window, message, window_param, data_param);
483 /*============================================================================*
485 *============================================================================*/
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;
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;
507 /*============================================================================*
509 *============================================================================*/
512 * @addtogroup Ecore_Win32_Group Ecore_Win32 library
514 * Ecore_Win32 is a library that wraps Windows graphic functions
515 * and integrate them nicely into the Ecore main loop.
517 * @section Ecore_Win32_Sec_Init Initialisation / Shutdown
521 * @section Ecore_Win32_Sec_Icons How to set icons to an application
523 * It is possible to also sets the icon of the application easily:
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:
533 * 101 ICON DISCARDABLE "my_icon.ico"
535 * @li With Visual Studio, put that file in the 'Resource file' part
537 * @li With MinGW, you have to compile it with windres:
539 * windres my_icon_rc.rc my_icon_rc.o
541 * and add my_icon_rc.o to the object files of the application.
543 * @note The value 101 must not be changed, it's the ID used
544 * internally by Ecore_Win32 to get the icons.
550 * @brief Initialize the Ecore_Win32 library.
552 * @return 1 or greater on success, 0 on error.
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
558 * When Ecore_Win32 is not used anymore, call ecore_win32_shutdown()
559 * to shut down the Ecore_Win32 library.
568 if (++_ecore_win32_init_count != 1)
569 return _ecore_win32_init_count;
572 return --_ecore_win32_init_count;
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)
578 EINA_LOG_ERR("Ecore_Win32: Could not register log domain");
582 if (!ecore_event_init())
584 ERR("Ecore_Win32: Could not init ecore_event");
585 goto unregister_log_domain;
588 _ecore_win32_instance = GetModuleHandle(NULL);
589 if (!_ecore_win32_instance)
591 ERR("GetModuleHandle() failed");
592 goto shutdown_ecore_event;
595 icon = LoadImage(_ecore_win32_instance,
596 MAKEINTRESOURCE(IDI_ICON),
598 GetSystemMetrics(SM_CXICON),
599 GetSystemMetrics(SM_CYICON),
601 icon_sm = LoadImage(_ecore_win32_instance,
602 MAKEINTRESOURCE(IDI_ICON),
604 GetSystemMetrics(SM_CXSMICON),
605 GetSystemMetrics(SM_CYSMICON),
608 icon = LoadIcon (NULL, IDI_APPLICATION);
610 icon_sm = LoadIcon (NULL, IDI_APPLICATION);
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;
618 wc.hInstance = _ecore_win32_instance;
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;
626 if(!RegisterClassEx(&wc))
628 ERR("RegisterClass() failed");
632 if (!ecore_win32_dnd_init())
634 ERR("ecore_win32_dnd_init() failed");
635 goto unregister_class;
638 if (!ECORE_WIN32_EVENT_MOUSE_IN)
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();
654 return _ecore_win32_init_count;
657 UnregisterClass(ECORE_WIN32_WINDOW_CLASS, _ecore_win32_instance);
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);
667 return --_ecore_win32_init_count;
671 * @brief Shut down the Ecore_Win32 library.
673 * @return 0 when the library is completely shut down, 1 or
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.
681 ecore_win32_shutdown()
683 if (--_ecore_win32_init_count != 0)
684 return _ecore_win32_init_count;
686 ecore_win32_dnd_shutdown();
688 if (!UnregisterClass(ECORE_WIN32_WINDOW_CLASS, _ecore_win32_instance))
689 INF("UnregisterClass() failed");
691 if (!FreeLibrary(_ecore_win32_instance))
692 INF("FreeLibrary() failed");
694 _ecore_win32_instance = NULL;
696 ecore_event_shutdown();
697 eina_log_domain_unregister(_ecore_win32_log_dom_global);
698 _ecore_win32_log_dom_global = -1;
701 return _ecore_win32_init_count;
705 * @brief Retrieve the depth of the screen.
707 * @return The depth of the screen.
709 * This function returns the depth of the screen. If an error occurs,
713 ecore_win32_screen_depth_get()
718 INF("getting screen depth");
723 ERR("GetDC() failed");
727 depth = GetDeviceCaps(dc, BITSPIXEL);
728 if (!ReleaseDC(NULL, dc))
730 ERR("ReleaseDC() failed (device context not released)");
737 * @brief Sets the timeout for a double and triple clicks to be flagged.
739 * @param t The time in seconds.
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.
746 ecore_win32_double_click_time_set(double t)
748 if (t < 0.0) t = 0.0;
749 _ecore_win32_double_click_time = t;
753 * @brief Retrieve the double and triple click flag timeout.
755 * @return The timeout for double clicks in seconds.
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.
763 ecore_win32_double_click_time_get(void)
765 return _ecore_win32_double_click_time;
769 * @brief Return the last event time.
771 * @return The last envent time.
773 * This function returns the last event time.
776 ecore_win32_current_time_get(void)
778 return _ecore_win32_event_last_time;