[ecore] merged svn latest code (svn54830)
[profile/ivi/ecore.git] / src / lib / ecore_wince / ecore_wince_window.c
1 #ifdef HAVE_CONFIG_H
2 # include <config.h>
3 #endif
4
5 #define WIN32_LEAN_AND_MEAN
6 #include <windows.h>
7 #undef WIN32_LEAN_AND_MEAN
8
9 #include <Evil.h>
10 #include <Eina.h>
11
12 #include "Ecore_WinCE.h"
13 #include "ecore_wince_private.h"
14
15 /*============================================================================*
16  *                                  Local                                     *
17  *============================================================================*/
18
19 /**
20  * @cond LOCAL
21  */
22
23
24 typedef BOOL (__stdcall *UnregisterFunc1Proc)(UINT, UINT);
25
26 static int
27 _ecore_wince_hardware_keys_register(HWND window)
28 {
29    HINSTANCE           core_dll;
30    UnregisterFunc1Proc unregister_fct;
31    int                 i;
32
33    core_dll = LoadLibrary(L"coredll.dll");
34    if (!core_dll)
35      {
36         ERR("LoadLibrary() failed");
37         return 0;
38      }
39
40    unregister_fct = (UnregisterFunc1Proc)GetProcAddress(core_dll, L"UnregisterFunc1");
41    if (!unregister_fct)
42      {
43         ERR("GetProcAddress() failed");
44         FreeLibrary(core_dll);
45         return 0;
46      }
47
48    for (i = 0xc1; i <= 0xcf; i++)
49      {
50         unregister_fct(MOD_WIN, i);
51         RegisterHotKey(window, i, MOD_WIN, i);
52      }
53
54    FreeLibrary(core_dll);
55
56    return 1;
57 }
58
59 /**
60  * @endcond
61  */
62
63
64 /*============================================================================*
65  *                                 Global                                     *
66  *============================================================================*/
67
68 /*============================================================================*
69  *                                   API                                      *
70  *============================================================================*/
71
72 /**
73  * @addtogroup Ecore_WinCE_Group Ecore_WinCE library
74  *
75  * @{
76  */
77
78 /**
79  * @brief Creates a new window.
80  *
81  * @param parent The parent window.
82  * @param x The x coordinate of the top-left corner of the window.
83  * @param y The y coordinate of the top-left corner of the window.
84  * @param width The width of the window.
85  * @param height The height of hte window.
86  * @return A newly allocated window.
87  *
88  * This function creates a new window which parent is @p parent. @p width and
89  * @p height are the size of the window content (the client part),
90  * without the border and title bar. @p x and @p y are the system
91  * coordinates of the top left cerner of the window (that is, of the
92  * title bar). This function returns a newly created window on
93  * success, and @c NULL on failure.
94  */
95 EAPI Ecore_WinCE_Window *
96 ecore_wince_window_new(Ecore_WinCE_Window *parent,
97                        int                 x,
98                        int                 y,
99                        int                 width,
100                        int                 height)
101 {
102    struct _Ecore_WinCE_Window *w;
103    HWND                        window;
104    RECT                        rect;
105
106    INF("creating window");
107
108    w = (struct _Ecore_WinCE_Window *)calloc(1, sizeof(struct _Ecore_WinCE_Window));
109    if (!w)
110      {
111         ERR("malloc() failed");
112         return NULL;
113      }
114
115    rect.left = 0;
116    rect.top = 0;
117    rect.right = width;
118    rect.bottom = height;
119    if (!AdjustWindowRectEx(&rect, WS_CAPTION | WS_SYSMENU | WS_VISIBLE, FALSE, WS_EX_TOPMOST))
120      {
121         ERR("AdjustWindowRectEx() failed");
122         free(w);
123         return NULL;
124      }
125
126    window = CreateWindowEx(WS_EX_TOPMOST,
127                            ECORE_WINCE_WINDOW_CLASS,
128                            L"",
129                            WS_CAPTION | WS_SYSMENU | WS_VISIBLE,
130                            x, y,
131                            rect.right - rect.left, rect.bottom - rect.top,
132                            parent ? ((struct _Ecore_WinCE_Window *)parent)->window : NULL,
133                            NULL, _ecore_wince_instance, NULL);
134    if (!window)
135      {
136         ERR("CreateWindowEx() failed");
137         free(w);
138         return NULL;
139      }
140
141    if (!_ecore_wince_hardware_keys_register(window))
142      {
143         ERR("_ecore_wince_hardware_keys_register() failed");
144         DestroyWindow(window);
145         free(w);
146         return NULL;
147      }
148
149    w->window = window;
150
151    SetLastError(0);
152    if (!SetWindowLong(window, GWL_USERDATA, (LONG)w) && (GetLastError() != 0))
153      {
154         ERR("SetWindowLong() failed");
155         DestroyWindow(window);
156         free(w);
157         return NULL;
158      }
159
160    w->pointer_is_in = 0;
161
162    return w;
163 }
164
165 /**
166  * @brief Free the given window.
167  *
168  * @param window The window to free.
169  *
170  * This function frees @p window. If @p window is @c NULL, this
171  * function does nothing.
172  */
173 EAPI void
174 ecore_wince_window_free(Ecore_WinCE_Window *window)
175 {
176    if (!window) return;
177
178    INF("destroying window");
179
180    DestroyWindow(((struct _Ecore_WinCE_Window *)window)->window);
181    free(window);
182 }
183
184 /**
185  * @brief Return the window HANDLE associated to the given window.
186  *
187  * @param window The window to retrieve the HANDLE from.
188  *
189  * This function returns the window HANDLE associated to @p window. If
190  * @p window is @c NULL, this function returns @c NULL.
191  */
192 EAPI void *
193 ecore_wince_window_hwnd_get(Ecore_WinCE_Window *window)
194 {
195    if (!window)
196      return NULL;
197
198    return ((struct _Ecore_WinCE_Window *)window)->window;
199 }
200
201 /**
202  * @brief Move the given window to a given position.
203  *
204  * @param window The window to move.
205  * @param x The x coordinate of the destination position.
206  * @param y The y coordinate of the destination position.
207  *
208  * This function move @p window to the new position of coordinates @p x
209  * and @p y. If @p window is @c NULL, or if it is fullscreen, or on
210  * error, this function does nothing.
211  */
212 EAPI void
213 ecore_wince_window_move(Ecore_WinCE_Window *window,
214                         int                 x,
215                         int                 y)
216 {
217    RECT rect;
218    HWND w;
219
220    if (!window || ((struct _Ecore_WinCE_Window *)window)->fullscreen)
221      return;
222
223    INF("moving window (%dx%d)", x, y);
224
225    w = ((struct _Ecore_WinCE_Window *)window)->window;
226    if (!GetWindowRect(w, &rect))
227      {
228         ERR("GetWindowRect() failed");
229         return;
230      }
231
232    if (!MoveWindow(w, x, y,
233                    rect.right - rect.left,
234                    rect.bottom - rect.top,
235                    TRUE))
236      {
237         ERR("MoveWindow() failed");
238      }
239 }
240
241 /**
242  * @brief Resize the given window to a given size.
243  *
244  * @param window The window to resize.
245  * @param width The new width.
246  * @param height The new height.
247  *
248  * This function resize @p window to the new @p width and @p height.
249  * If @p window is @c NULL, or if it is fullscreen, or on error, this
250  * function does nothing.
251  */
252 EAPI void
253 ecore_wince_window_resize(Ecore_WinCE_Window *window,
254                           int                 width,
255                           int                 height)
256 {
257    RECT                        rect;
258    struct _Ecore_WinCE_Window *w;
259    DWORD                       style;
260    DWORD                       exstyle;
261    int                         x;
262    int                         y;
263
264    if (!window || ((struct _Ecore_WinCE_Window *)window)->fullscreen)
265      return;
266
267    INF("resizing window (%dx%d)", width, height);
268
269    w = (struct _Ecore_WinCE_Window *)window;
270    if (!GetWindowRect(w->window, &rect))
271      {
272         ERR("GetWindowRect() failed");
273         return;
274      }
275
276    x = rect.left;
277    y = rect.top;
278    rect.left = 0;
279    rect.top = 0;
280    rect.right = width;
281    rect.bottom = height;
282    if (!(style = GetWindowLong(w->window, GWL_STYLE)))
283      {
284         ERR("GetWindowLong() failed");
285         return;
286      }
287    if (!(exstyle = GetWindowLong(w->window, GWL_EXSTYLE)))
288      {
289         ERR("GetWindowLong() failed");
290         return;
291      }
292    if (!AdjustWindowRectEx(&rect, style, FALSE, exstyle))
293      {
294         ERR("AdjustWindowRectEx() failed");
295         return;
296      }
297
298    if (!MoveWindow(w->window, x, y,
299                    rect.right - rect.left,
300                    rect.bottom - rect.top,
301                    FALSE))
302      {
303         ERR("MoveWindow() failed");
304      }
305 }
306
307 /**
308  * @brief Move and resize the given window to a given position and size.
309  *
310  * @param window The window to move and resize.
311  * @param x The x coordinate of the destination position.
312  * @param y The x coordinate of the destination position.
313  * @param width The new width.
314  * @param height The new height.
315  *
316  * This function resize @p window to the new position of coordinates @p x
317  * and @p y and the new @p width and @p height. If @p window is @c NULL,
318  * or if it is fullscreen, or on error, this function does nothing.
319  */
320 EAPI void
321 ecore_wince_window_move_resize(Ecore_WinCE_Window *window,
322                                int                 x,
323                                int                 y,
324                                int                 width,
325                                int                 height)
326 {
327    RECT                        rect;
328    struct _Ecore_WinCE_Window *w;
329    DWORD                       style;
330    DWORD                       exstyle;
331
332    if (!window || ((struct _Ecore_WinCE_Window *)window)->fullscreen)
333      return;
334
335    INF("moving and resizing window (%dx%d %dx%d)", x, y, width, height);
336
337    w = ((struct _Ecore_WinCE_Window *)window);
338    rect.left = 0;
339    rect.top = 0;
340    rect.right = width;
341    rect.bottom = height;
342    if (!(style = GetWindowLong(w->window, GWL_STYLE)))
343      {
344         ERR("GetWindowLong() failed");
345         return;
346      }
347    if (!(exstyle = GetWindowLong(w->window, GWL_EXSTYLE)))
348      {
349         ERR("GetWindowLong() failed");
350         return;
351      }
352    if (!AdjustWindowRectEx(&rect, style, FALSE, exstyle))
353      {
354         ERR("AdjustWindowRectEx() failed");
355         return;
356      }
357
358    if (!MoveWindow(w->window, x, y,
359               rect.right - rect.left,
360               rect.bottom - rect.top,
361               TRUE))
362      {
363         ERR("MoveWindow() failed");
364      }
365 }
366
367 /**
368  * @brief Show the given window.
369  *
370  * @param window The window to show.
371  *
372  * This function shows @p window. If @p window is @c NULL, or on
373  * error, this function does nothing.
374  */
375 EAPI void
376 ecore_wince_window_show(Ecore_WinCE_Window *window)
377 {
378    if (!window) return;
379
380    INF("showing window");
381
382    if (!ShowWindow(((struct _Ecore_WinCE_Window *)window)->window, SW_SHOWNORMAL))
383      {
384         ERR("ShowWindow() failed");
385         return;
386      }
387    if (!UpdateWindow(((struct _Ecore_WinCE_Window *)window)->window))
388      {
389         ERR("UpdateWindow() failed");
390      }
391    if (!SendMessage(((struct _Ecore_WinCE_Window *)window)->window, WM_SHOWWINDOW, 1, 0))
392      {
393         ERR("SendMessage() failed");
394      }
395 }
396
397 /**
398  * @brief Hide the given window.
399  *
400  * @param window The window to show.
401  *
402  * This function hides @p window. If @p window is @c NULL, or on
403  * error, this function does nothing.
404  */
405 EAPI void
406 ecore_wince_window_hide(Ecore_WinCE_Window *window)
407 {
408    if (!window) return;
409
410    INF("hiding window");
411
412    if (!ShowWindow(((struct _Ecore_WinCE_Window *)window)->window, SW_HIDE))
413      {
414         ERR("ShowWindow() failed");
415         return;
416      }
417    if (!SendMessage(((struct _Ecore_WinCE_Window *)window)->window, WM_SHOWWINDOW, 0, 0))
418      {
419         ERR("SendMessage() failed");
420      }
421 }
422
423 /**
424  * @brief Set the title of the given window.
425  *
426  * @param window The window to set the title.
427  * @param title The new title.
428  *
429  * This function sets the title of @p window to @p title. If @p window
430  * is @c NULL, or if @p title is @c NULL or empty, or on error, this
431  * function does nothing.
432  */
433 EAPI void
434 ecore_wince_window_title_set(Ecore_WinCE_Window *window,
435                              const char         *title)
436 {
437    wchar_t *wtitle;
438
439    if (!window) return;
440
441    if (!title || !title[0]) return;
442
443    INF("setting window title");
444
445    wtitle = evil_char_to_wchar(title);
446    if (!wtitle) return;
447
448    if (!SetWindowText(((struct _Ecore_WinCE_Window *)window)->window, wtitle))
449      {
450         ERR("SetWindowText() failed");
451      }
452    free(wtitle);
453 }
454
455 /**
456  * @brief Set the graphic backend used for the given window.
457  *
458  * @param window The window.
459  * @param backend The backend.
460  *
461  * This function sets the graphic backend to use with @p window to
462  * @p backend. If @p window if @c NULL, this function does nothing.
463  *
464  * The valid values for @p backend are
465  *
466  * @li 0: automatic choice of the backend.
467  * @li 1: the framebuffer (fast but could be not well suported).
468  * @li 2: GAPI (less fast but almost always supported).
469  * @li 3: DirectDraw (less fast than GAPI but almost always
470  * supported).
471  * @li 4: GDI (the slowest but always supported).
472  *
473  * The @p backend is used only in Evas and Ecore_Evas. So this
474  * function should not be called if Ecore_Evas is used.
475  */
476 EAPI void
477 ecore_wince_window_backend_set(Ecore_WinCE_Window *window,
478                                int                 backend)
479 {
480    struct _Ecore_WinCE_Window *w;
481
482    if (!window)
483      return;
484
485    INF("setting backend");
486
487    w = (struct _Ecore_WinCE_Window *)window;
488    w->backend = backend;
489 }
490
491 /**
492  * @brief Set the suspend callback used for the given window.
493  *
494  * @param window The window.
495  * @param suspend_cb The suspend callback.
496  *
497  * This function sets the suspend callback to use with @p window to
498  * @p suspend_cb. If @p window if @c NULL, this function does nothing.
499  *
500  * The @p suspend_cb is used only in Evas and Ecore_Evas. So this
501  * function should not be called if Ecore_Evas is used.
502  */
503 EAPI void
504 ecore_wince_window_suspend_set(Ecore_WinCE_Window *window, int (*suspend_cb)(int))
505 {
506    struct _Ecore_WinCE_Window *w;
507
508    if (!window)
509      return;
510
511    INF("setting suspend callback");
512
513    w = (struct _Ecore_WinCE_Window *)window;
514    w->suspend = suspend;
515 }
516
517 /**
518  * @brief Set the resume callback used for the given window.
519  *
520  * @param window The window.
521  * @param resume_cb The resume callback.
522  *
523  * This function sets the resume callback to use with @p window to
524  * @p resume_cb. If @p window if @c NULL, this function does nothing.
525  *
526  * The @p resume_cb is used only in Evas and Ecore_Evas. So this
527  * function should not be called if Ecore_Evas is used.
528  */
529 EAPI void
530 ecore_wince_window_resume_set(Ecore_WinCE_Window *window, int (*resume_cb)(int))
531 {
532    struct _Ecore_WinCE_Window *w;
533
534    if (!window)
535      return;
536
537    INF("setting resume callback");
538
539    w = (struct _Ecore_WinCE_Window *)window;
540    w->resume = resume;
541 }
542
543 /**
544  * @brief Get the geometry of the given window.
545  *
546  * @param window The window to retrieve the geometry from.
547  * @param x The x coordinate of the position.
548  * @param y The x coordinate of the position.
549  * @param width The width.
550  * @param height The height.
551  *
552  * This function retrieves the position and size of @p window. @p x,
553  * @p y, @p width and @p height can be buffers that will be filled with
554  * the corresponding values. If one of them is @c NULL, nothing will
555  * be done for that parameter. If @p window is @c NULL, and if the
556  * buffers are not @c NULL, they will be filled with respectively 0,
557  * 0, the size of the screen and the height of the screen.
558  */
559 EAPI void
560 ecore_wince_window_geometry_get(Ecore_WinCE_Window *window,
561                                 int                *x,
562                                 int                *y,
563                                 int                *width,
564                                 int                *height)
565 {
566    RECT rect;
567    int  w;
568    int  h;
569
570    INF("getting window geometry");
571
572    if (!window)
573      {
574         if (x) *x = 0;
575         if (y) *y = 0;
576         if (width) *width = GetSystemMetrics(SM_CXSCREEN);
577         if (height) *height = GetSystemMetrics(SM_CYSCREEN);
578
579         return;
580      }
581
582    if (!GetClientRect(((struct _Ecore_WinCE_Window *)window)->window,
583                       &rect))
584      {
585         ERR("GetClientRect() failed");
586
587         if (x) *x = 0;
588         if (y) *y = 0;
589         if (width) *width = 0;
590         if (height) *height = 0;
591
592         return;
593      }
594
595    w = rect.right - rect.left;
596    h = rect.bottom - rect.top;
597
598    if (!GetWindowRect(((struct _Ecore_WinCE_Window *)window)->window,
599                       &rect))
600      {
601         ERR("GetWindowRect() failed");
602
603         if (x) *x = 0;
604         if (y) *y = 0;
605         if (width) *width = 0;
606         if (height) *height = 0;
607
608         return;
609      }
610
611    if (x) *x = rect.left;
612    if (y) *y = rect.top;
613    if (width) *width = w;
614    if (height) *height = h;
615 }
616
617 /**
618  * @brief Get the size of the given window.
619  *
620  * @param window The window to retrieve the size from.
621  * @param width The width.
622  * @param height The height.
623  *
624  * This function retrieves the size of @p window. @p width and
625  * @p height can be buffers that will be filled with the corresponding
626  * values. If one of them is @c NULL, nothing will be done for that
627  * parameter. If @p window is @c NULL, and if the buffers are not
628  * @c NULL, they will be filled with respectively the size of the screen
629  * and the height of the screen.
630  */
631 EAPI void
632 ecore_wince_window_size_get(Ecore_WinCE_Window *window,
633                             int                *width,
634                             int                *height)
635 {
636    RECT rect;
637
638    INF("getting window size");
639
640    if (!window)
641      {
642         if (width) *width = GetSystemMetrics(SM_CXSCREEN);
643         if (height) *height = GetSystemMetrics(SM_CYSCREEN);
644
645         return;
646      }
647
648    if (!GetClientRect(((struct _Ecore_WinCE_Window *)window)->window,
649                       &rect))
650      {
651         ERR("GetClientRect() failed");
652
653         if (width) *width = 0;
654         if (height) *height = 0;
655      }
656
657    if (width) *width = rect.right - rect.left;
658    if (height) *height = rect.bottom - rect.top;
659 }
660
661 /**
662  * @brief Set the given window to fullscreen.
663  *
664  * @param window The window.
665  * @param on EINA_TRUE for fullscreen mode, EINA_FALSE for windowed mode.
666  *
667  * This function set @p window to fullscreen or windowed mode. If @p on
668  * is set to EINA_TRUE, the window will be fullscreen, if it is set to
669  * EINA_FALSE, it will be windowed. If @p window is @c NULL or if the
670  * state does not change (like setting to fullscreen while the window
671  * is already fullscreen), this function does nothing.
672  */
673 EAPI void
674 ecore_wince_window_fullscreen_set(Ecore_WinCE_Window *window,
675                                   Eina_Bool           on)
676 {
677    struct _Ecore_WinCE_Window *ew;
678    HWND                        w;
679    HWND                        task_bar;
680
681    if (!window) return;
682
683    ew = (struct _Ecore_WinCE_Window *)window;
684    if (((ew->fullscreen) && (on)) ||
685        ((!ew->fullscreen) && (!on)))
686      return;
687
688    INF("setting fullscreen: %s", on ? "yes" : "no");
689
690    ew->fullscreen = !!on;
691    w = ew->window;
692
693    if (on)
694      {
695         /* save the position and size of the window */
696         if (!GetWindowRect(w, &ew->rect))
697           {
698              ERR("GetWindowRect() failed");
699              return;
700           }
701
702         /* hide task bar */
703         task_bar = FindWindow(L"HHTaskBar", NULL);
704         if (!task_bar)
705           {
706              INF("FindWindow(): can not find task bar");
707           }
708         if (!ShowWindow(task_bar, SW_HIDE))
709           {
710              INF("ShowWindow(): task bar already hidden");
711           }
712         if (!EnableWindow(task_bar, FALSE))
713           {
714              INF("EnableWindow(): input already disabled");
715           }
716
717         /* style: visible + popup */
718         if (!SetWindowLong(w, GWL_STYLE, WS_POPUP | WS_VISIBLE))
719           {
720              INF("SetWindowLong() failed");
721           }
722
723         /* resize window to fit the entire screen */
724         if (!SetWindowPos(w, HWND_TOPMOST,
725                           0, 0,
726                           GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN),
727                           SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED))
728           {
729              INF("SetWindowPos() failed");
730           }
731         /*
732          * It seems that SetWindowPos is not sufficient.
733          * Call MoveWindow with the correct size and force painting.
734          * Note that UpdateWindow (forcing repainting) is not sufficient
735          */
736         if (!MoveWindow(w,
737                         0, 0,
738                         GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN),
739                         TRUE))
740           {
741              INF("MoveWindow() failed");
742           }
743      }
744    else
745      {
746         /* show task bar */
747         task_bar = FindWindow(L"HHTaskBar", NULL);
748         if (!task_bar)
749           {
750              INF("FindWindow(): can not find task bar");
751           }
752         if (!ShowWindow(task_bar, SW_SHOW))
753           {
754              INF("ShowWindow(): task bar already visible");
755           }
756         if (!EnableWindow(task_bar, TRUE))
757           {
758              INF("EnableWindow():  input already enabled");
759           }
760
761         /* style: visible + caption + sysmenu */
762         if (!SetWindowLong(w, GWL_STYLE, WS_CAPTION | WS_SYSMENU | WS_VISIBLE))
763           {
764              INF("SetWindowLong() failed");
765           }
766         /* restaure the position and size of the window */
767         if (!SetWindowPos(w, HWND_TOPMOST,
768                           ew->rect.left,
769                           ew->rect.top,
770                           ew->rect.right - ew->rect.left,
771                           ew->rect.bottom - ew->rect.top,
772                           SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED))
773           {
774              INF("SetWindowLong() failed");
775           }
776         /*
777          * It seems that SetWindowPos is not sufficient.
778          * Call MoveWindow with the correct size and force painting.
779          * Note that UpdateWindow (forcing repainting) is not sufficient
780          */
781         if (!MoveWindow(w,
782                         ew->rect.left,
783                         ew->rect.top,
784                         ew->rect.right - ew->rect.left,
785                         ew->rect.bottom - ew->rect.top,
786                         TRUE))
787           {
788              INF("MoveWindow() failed");
789           }
790      }
791 }
792
793 /**
794  * @}
795  */