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->timestamp = GetMessageTime();
77 coord = GetMessagePos();
78 point = MAKEPOINTS(coord);
81 data->discard_ctrl = EINA_FALSE;
83 switch (data->message)
85 /* Keyboard input notifications */
88 if ((data->message == WM_KEYDOWN) &&
89 (data->window_param == VK_CONTROL) &&
90 ((HIWORD(data->data_param) & KF_EXTENDED) == 0))
92 /* Ctrl left key is pressed */
97 * we check if the next message
99 * - has the same timestamp than the Ctrl one
100 * - is the key press of the right Alt key
102 res = PeekMessage(&next_msg, data->window,
103 WM_KEYDOWN, WM_KEYDOWN,
106 (next_msg.wParam == VK_MENU) &&
107 (next_msg.time == data->timestamp) &&
108 (HIWORD(next_msg.lParam) & KF_EXTENDED))
110 INF("discard left Ctrl key press (sent by AltGr key press)");
111 data->discard_ctrl = EINA_TRUE;
114 _ecore_win32_event_handle_key_press(data, 1);
119 _ecore_win32_event_handle_key_press(data, 0);
123 INF("keyup message");
124 if ((data->window_param == VK_CONTROL) &&
125 ((HIWORD(data->data_param) & KF_EXTENDED) == 0))
127 /* Ctrl left key is pressed */
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
137 res = PeekMessage(&next_msg, data->window,
138 WM_KEYUP, WM_SYSKEYUP,
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))
147 INF("discard left Ctrl key release (sent by AltGr key release)");
148 data->discard_ctrl = EINA_TRUE;
151 _ecore_win32_event_handle_key_release(data);
154 INF("setfocus message");
155 _ecore_win32_event_handle_focus_in(data);
158 INF("kill focus message");
159 _ecore_win32_event_handle_focus_out(data);
161 /* Mouse input notifications */
163 INF("left button down message");
165 _ecore_win32_event_handle_button_press(data, 1);
168 INF("middle button down message");
169 _ecore_win32_event_handle_button_press(data, 2);
172 INF("right button down message");
173 _ecore_win32_event_handle_button_press(data, 3);
177 Ecore_Win32_Window *w = NULL;
179 INF("left button up message");
182 w = (Ecore_Win32_Window *)GetWindowLongPtr(window, GWLP_USERDATA);
183 if (w->drag.dragging)
185 w->drag.dragging = 0;
189 _ecore_win32_event_handle_button_release(data, 1);
193 INF("middle button up message");
194 _ecore_win32_event_handle_button_release(data, 2);
197 INF("right button up message");
198 _ecore_win32_event_handle_button_release(data, 3);
203 Ecore_Win32_Window *w = NULL;
205 INF("moue move message");
207 w = (Ecore_Win32_Window *)GetWindowLongPtr(window, GWLP_USERDATA);
209 if (w->drag.dragging)
213 pt.x = GET_X_LPARAM(data_param);
214 pt.y = GET_Y_LPARAM(data_param);
215 if (ClientToScreen(window, &pt))
217 if (w->drag.type == HTCAPTION)
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);
231 if (w->drag.type == HTLEFT)
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);
243 if (w->drag.type == HTRIGHT)
247 dw = pt.x - w->drag.px;
248 ecore_win32_window_resize(w, w->drag.w + dw, w->drag.h);
254 if (w->drag.type == HTTOP)
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);
266 if (w->drag.type == HTBOTTOM)
270 dh = pt.y - w->drag.py;
271 ecore_win32_window_resize(w, w->drag.w, w->drag.h + dh);
277 if (w->drag.type == HTTOPLEFT)
284 dw = pt.x - w->drag.px;
285 dh = pt.y - w->drag.py;
288 _ecore_win32_size_check(w,
289 w->drag.w - dw, w->drag.h - dh,
292 ecore_win32_window_move_resize(w, w->drag.x + dx, w->drag.y + dy, w->drag.w - dw, w->drag.h - dh);
301 if (w->drag.type == HTTOPRIGHT)
308 dw = pt.x - w->drag.px;
309 dh = pt.y - w->drag.py;
312 _ecore_win32_size_check(w,
313 w->drag.w, w->drag.h - dh,
315 ecore_win32_window_move_resize(w, w->drag.x, w->drag.y + dy, w->drag.w, w->drag.h - dh);
323 if (w->drag.type == HTBOTTOMLEFT)
330 dw = pt.x - w->drag.px;
331 dh = pt.y - w->drag.py;
334 _ecore_win32_size_check(w,
335 w->drag.w - dw, w->drag.h + dh,
337 ecore_win32_window_move_resize(w, w->drag.x + dx, w->drag.y, w->drag.w - dw, w->drag.h + dh);
345 if (w->drag.type == HTBOTTOMRIGHT)
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);
362 if (GetClientRect(window, &rect))
366 INF("mouse in window");
368 pt.x = GET_X_LPARAM(data_param);
369 pt.y = GET_Y_LPARAM(data_param);
370 if (!PtInRect(&rect, pt))
372 if (w->pointer_is_in)
374 w->pointer_is_in = 0;
375 _ecore_win32_event_handle_leave_notify(data);
380 if (!w->pointer_is_in)
382 w->pointer_is_in = 1;
383 _ecore_win32_event_handle_enter_notify(data);
389 ERR("GetClientRect() failed");
391 _ecore_win32_event_handle_motion_notify(data);
396 INF("mouse wheel message");
397 _ecore_win32_event_handle_button_press(data, 4);
399 /* Window notifications */
401 INF("create window message");
402 _ecore_win32_event_handle_create_notify(data);
405 INF("destroy window message");
406 _ecore_win32_event_handle_destroy_notify(data);
409 INF("show window message");
410 if ((data->data_param == SW_OTHERUNZOOM) ||
411 (data->data_param == SW_OTHERZOOM))
414 if (data->window_param)
415 _ecore_win32_event_handle_map_notify(data);
417 _ecore_win32_event_handle_unmap_notify(data);
421 INF("close window message");
422 _ecore_win32_event_handle_delete_request(data);
424 case WM_GETMINMAXINFO:
425 INF("get min max info window message");
428 INF("moving window message");
429 _ecore_win32_event_handle_configure_notify(data);
432 INF("move window message");
435 INF("sizing window message");
436 _ecore_win32_event_handle_resize(data);
437 _ecore_win32_event_handle_configure_notify(data);
440 INF("size window message");
442 /* case WM_WINDOWPOSCHANGING: */
445 /* GetClientRect(window, &rect); */
446 /* printf (" *** ecore message : WINDOWPOSCHANGING %ld %ld\n", */
447 /* rect.right - rect.left, rect.bottom - rect.top); */
449 /* _ecore_win32_event_handle_configure_notify(data); */
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);
456 case WM_ENTERSIZEMOVE:
457 INF("enter size move window message");
459 case WM_EXITSIZEMOVE:
460 INF("exit size move window message");
462 case WM_NCLBUTTONDOWN:
463 INF("non client left button down window message");
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))
475 Ecore_Win32_Window *w;
477 w = (Ecore_Win32_Window *)GetWindowLongPtr(window, GWLP_USERDATA);
478 ecore_win32_window_geometry_get(w,
480 &w->drag.w, &w->drag.h);
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;
488 return DefWindowProc(window, message, window_param, data_param);
490 INF("sys command window message %d", (int)window_param);
492 if ((((DWORD)window_param & 0xfff0) == SC_MOVE) ||
493 (((DWORD)window_param & 0xfff0) == SC_SIZE))
495 Ecore_Win32_Window *w;
497 INF("sys command MOVE or SIZE window message : %dx%d", GET_X_LPARAM(data_param), GET_Y_LPARAM(data_param));
499 w = (Ecore_Win32_Window *)GetWindowLongPtr(window, GWLP_USERDATA);
500 w->drag.dragging = 1;
503 return DefWindowProc(window, message, window_param, data_param);
504 /* GDI notifications */
511 INF("paint message");
513 if (GetUpdateRect(window, &rect, FALSE))
518 hdc = BeginPaint(window, &ps);
520 _ecore_win32_event_handle_expose(data);
521 EndPaint(window, &ps);
526 INF("set redraw message");
529 INF("sync paint message");
532 return DefWindowProc(window, message, window_param, data_param);
541 /*============================================================================*
543 *============================================================================*/
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;
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;
565 /*============================================================================*
567 *============================================================================*/
570 * @addtogroup Ecore_Win32_Group Ecore_Win32 library
572 * Ecore_Win32 is a library that wraps Windows graphic functions
573 * and integrate them nicely into the Ecore main loop.
575 * @section Ecore_Win32_Sec_Init Initialisation / Shutdown
579 * @section Ecore_Win32_Sec_Icons How to set icons to an application
581 * It is possible to also sets the icon of the application easily:
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:
591 * 101 ICON DISCARDABLE "my_icon.ico"
593 * @li With Visual Studio, put that file in the 'Resource file' part
595 * @li With MinGW, you have to compile it with windres:
597 * windres my_icon_rc.rc my_icon_rc.o
599 * and add my_icon_rc.o to the object files of the application.
601 * @note The value 101 must not be changed, it's the ID used
602 * internally by Ecore_Win32 to get the icons.
608 * @brief Initialize the Ecore_Win32 library.
610 * @return 1 or greater on success, 0 on error.
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
616 * When Ecore_Win32 is not used anymore, call ecore_win32_shutdown()
617 * to shut down the Ecore_Win32 library.
626 if (++_ecore_win32_init_count != 1)
627 return _ecore_win32_init_count;
630 return --_ecore_win32_init_count;
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)
636 EINA_LOG_ERR("Ecore_Win32: Could not register log domain");
640 if (!ecore_event_init())
642 ERR("Ecore_Win32: Could not init ecore_event");
643 goto unregister_log_domain;
646 _ecore_win32_instance = GetModuleHandle(NULL);
647 if (!_ecore_win32_instance)
649 ERR("GetModuleHandle() failed");
650 goto shutdown_ecore_event;
653 icon = LoadImage(_ecore_win32_instance,
654 MAKEINTRESOURCE(IDI_ICON),
656 GetSystemMetrics(SM_CXICON),
657 GetSystemMetrics(SM_CYICON),
659 icon_sm = LoadImage(_ecore_win32_instance,
660 MAKEINTRESOURCE(IDI_ICON),
662 GetSystemMetrics(SM_CXSMICON),
663 GetSystemMetrics(SM_CYSMICON),
666 icon = LoadIcon (NULL, IDI_APPLICATION);
668 icon_sm = LoadIcon (NULL, IDI_APPLICATION);
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;
676 wc.hInstance = _ecore_win32_instance;
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;
684 if(!RegisterClassEx(&wc))
686 ERR("RegisterClass() failed");
690 if (!ecore_win32_dnd_init())
692 ERR("ecore_win32_dnd_init() failed");
693 goto unregister_class;
696 if (!ECORE_WIN32_EVENT_MOUSE_IN)
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();
712 return _ecore_win32_init_count;
715 UnregisterClass(ECORE_WIN32_WINDOW_CLASS, _ecore_win32_instance);
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);
725 return --_ecore_win32_init_count;
729 * @brief Shut down the Ecore_Win32 library.
731 * @return 0 when the library is completely shut down, 1 or
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.
739 ecore_win32_shutdown()
741 if (--_ecore_win32_init_count != 0)
742 return _ecore_win32_init_count;
744 ecore_win32_dnd_shutdown();
746 if (!UnregisterClass(ECORE_WIN32_WINDOW_CLASS, _ecore_win32_instance))
747 INF("UnregisterClass() failed");
749 if (!FreeLibrary(_ecore_win32_instance))
750 INF("FreeLibrary() failed");
752 _ecore_win32_instance = NULL;
754 ecore_event_shutdown();
755 eina_log_domain_unregister(_ecore_win32_log_dom_global);
756 _ecore_win32_log_dom_global = -1;
759 return _ecore_win32_init_count;
763 * @brief Retrieve the depth of the screen.
765 * @return The depth of the screen.
767 * This function returns the depth of the screen. If an error occurs,
771 ecore_win32_screen_depth_get()
776 INF("getting screen depth");
781 ERR("GetDC() failed");
785 depth = GetDeviceCaps(dc, BITSPIXEL);
786 if (!ReleaseDC(NULL, dc))
788 ERR("ReleaseDC() failed (device context not released)");
795 * @brief Sets the timeout for a double and triple clicks to be flagged.
797 * @param t The time in seconds.
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.
804 ecore_win32_double_click_time_set(double t)
806 if (t < 0.0) t = 0.0;
807 _ecore_win32_double_click_time = t;
811 * @brief Retrieve the double and triple click flag timeout.
813 * @return The timeout for double clicks in seconds.
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.
821 ecore_win32_double_click_time_get(void)
823 return _ecore_win32_double_click_time;
827 * @brief Return the last event time.
829 * @return The last envent time.
831 * This function returns the last event time.
834 ecore_win32_current_time_get(void)
836 return _ecore_win32_event_last_time;