Source/WebKit/efl: [EFL] Add new pre-rendering code.
[WebKit-https.git] / Tools / EWebLauncher / main.c
1 /*
2  * Copyright (C) 2008 INdT - Instituto Nokia de Tecnologia
3  * Copyright (C) 2009, 2010 ProFUSION embedded systems
4  * Copyright (C) 2009, 2010, 2011 Samsung Electronics
5  *
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
18  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
21  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
25  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29
30 #include "EWebKit.h"
31
32 #include <ctype.h>
33 #include <Ecore.h>
34 #include <Ecore_Evas.h>
35 #include <Ecore_File.h>
36 #include <Ecore_Getopt.h>
37 #include <Ecore_X.h>
38 #include <Edje.h>
39 #include <Evas.h>
40 #include <limits.h>
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <string.h>
44 #include <sys/stat.h>
45 #include <sys/types.h>
46 #include <unistd.h>
47
48 #define DEFAULT_WIDTH      800
49 #define DEFAULT_HEIGHT     600
50 #define DEFAULT_ZOOM_INIT  1.0
51
52 #define info(format, args...)       \
53     do {                            \
54         if (verbose)                \
55             printf(format, ##args); \
56     } while (0)
57
58 #define MIN_ZOOM_LEVEL 0
59 #define DEFAULT_ZOOM_LEVEL 5
60 #define MAX_ZOOM_LEVEL 13
61
62 static int currentZoomLevel = DEFAULT_ZOOM_LEVEL;
63 static float currentZoom = 1.0;
64
65 // the zoom values are chosen to be like in Mozilla Firefox 3
66 static int zoomLevels[] = {30, 50, 67, 80, 90,
67                             100,
68                             110, 120, 133, 150, 170, 200, 240, 300};
69
70 static int verbose = 0;
71
72 static Eina_List *windows = NULL;
73
74 static char *themePath = NULL;
75
76 static const char *backingStores[] = {
77     "tiled",
78     "single",
79     NULL
80 };
81
82 typedef struct _Window_Properties {
83     Eina_Bool toolbarsVisible:1;
84     Eina_Bool statusbarVisible:1;
85     Eina_Bool scrollbarsVisible:1;
86     Eina_Bool menubarVisible:1;
87 } Window_Properties;
88
89 Window_Properties windowProperties = { /* Pretend we have them and they are initially visible */
90     EINA_TRUE,
91     EINA_TRUE,
92     EINA_TRUE,
93     EINA_TRUE
94 };
95
96 static const Ecore_Getopt options = {
97     "EWebLauncher",
98     "%prog [options] [url]",
99     "0.0.1",
100     "(C)2008 INdT (The Nokia Technology Institute)\n"
101     "(C)2009, 2010 ProFUSION embedded systems\n"
102     "(C)2009, 2010, 2011 Samsung Electronics",
103     "GPL",
104     "Test Web Browser using the Enlightenment Foundation Libraries of WebKit",
105     EINA_TRUE, {
106         ECORE_GETOPT_STORE_STR
107             ('e', "engine", "ecore-evas engine to use."),
108         ECORE_GETOPT_CALLBACK_NOARGS
109             ('E', "list-engines", "list ecore-evas engines.",
110              ecore_getopt_callback_ecore_evas_list_engines, NULL),
111         ECORE_GETOPT_CHOICE
112             ('b', "backing-store", "choose backing store to use.", backingStores),
113         ECORE_GETOPT_STORE_DEF_BOOL
114             ('f', "flattening", "frame flattening.", 0),
115         ECORE_GETOPT_STORE_DEF_BOOL
116             ('F', "fullscreen", "fullscreen mode.", 0),
117         ECORE_GETOPT_CALLBACK_ARGS
118             ('g', "geometry", "geometry to use in x:y:w:h form.", "X:Y:W:H",
119              ecore_getopt_callback_geometry_parse, NULL),
120         ECORE_GETOPT_STORE_STR
121             ('t', "theme", "path to read the theme file from."),
122         ECORE_GETOPT_STORE_STR
123             ('U', "user-agent", "custom user agent string to use."),
124         ECORE_GETOPT_COUNT
125             ('v', "verbose", "be more verbose."),
126         ECORE_GETOPT_VERSION
127             ('V', "version"),
128         ECORE_GETOPT_COPYRIGHT
129             ('R', "copyright"),
130         ECORE_GETOPT_LICENSE
131             ('L', "license"),
132         ECORE_GETOPT_HELP
133             ('h', "help"),
134         ECORE_GETOPT_SENTINEL
135     }
136 };
137
138 typedef struct _ELauncher {
139     Ecore_Evas *ee;
140     Evas *evas;
141     Evas_Object *bg;
142     Evas_Object *browser;
143     const char *theme;
144     const char *userAgent;
145     const char *backingStore;
146     unsigned char isFlattening;
147 } ELauncher;
148
149 static void browserDestroy(Ecore_Evas *ee);
150 static void closeWindow(Ecore_Evas *ee);
151 static int browserCreate(const char *url, const char *theme, const char *userAgent, Eina_Rectangle geometry, const char *engine, const char *backingStore, unsigned char isFlattening, unsigned char isFullscreen, const char *databasePath);
152
153 static void
154 print_history(Eina_List *list)
155 {
156     Eina_List *l;
157     void *d;
158
159     if (!verbose)
160        return;
161
162     printf("Session history contains:\n");
163
164     EINA_LIST_FOREACH(list, l, d) {
165        Ewk_History_Item *item = (Ewk_History_Item*)d;
166        cairo_surface_t *cs = ewk_history_item_icon_surface_get(item);
167        char buf[PATH_MAX];
168        int s = snprintf(buf, sizeof(buf), "/tmp/favicon-%s.png", ewk_history_item_uri_original_get(item));
169        for (s--; s >= (int)sizeof("/tmp/favicon-"); s--) {
170            if (!isalnum(buf[s]) && buf[s] != '.')
171                buf[s] = '_';
172        }
173        cs = ewk_history_item_icon_surface_get(item);
174
175        if (cs && cairo_surface_status(cs) == CAIRO_STATUS_SUCCESS)
176            cairo_surface_write_to_png(cs, buf);
177        else
178            buf[0] = '\0';
179
180        printf("* '%s' title='%s' icon='%s'\n",
181               ewk_history_item_uri_original_get(item),
182               ewk_history_item_title_get(item), buf);
183     }
184 }
185
186 static int
187 nearest_zoom_level_get(float factor)
188 {
189     int i, intFactor = (int)(factor * 100.0);
190     for (i = 0; zoomLevels[i] <= intFactor; i++) { }
191     printf("factor=%f, intFactor=%d, zoomLevels[%d]=%d, zoomLevels[%d]=%d\n",
192            factor, intFactor, i-1, zoomLevels[i-1], i, zoomLevels[i]);
193     if (intFactor - zoomLevels[i-1] < zoomLevels[i] - intFactor)
194         return i - 1;
195     return i;
196 }
197
198 static Eina_Bool
199 zoom_level_set(Evas_Object *webview, int level)
200 {
201     float factor = ((float) zoomLevels[level]) / 100.0;
202     Evas_Coord ox, oy, mx, my, cx, cy;
203     evas_pointer_canvas_xy_get(evas_object_evas_get(webview), &mx, &my);
204     evas_object_geometry_get(webview, &ox, &oy, NULL, NULL);
205     cx = mx - ox;
206     cy = my - oy;
207     return ewk_view_zoom_animated_set(webview, factor, 0.5, cx, cy);
208 }
209
210 static void
211 on_ecore_evas_resize(Ecore_Evas *ee)
212 {
213     Evas_Object *webview;
214     Evas_Object *bg;
215     int w, h;
216
217     ecore_evas_geometry_get(ee, NULL, NULL, &w, &h);
218
219     bg = evas_object_name_find(ecore_evas_get(ee), "bg");
220     evas_object_move(bg, 0, 0);
221     evas_object_resize(bg, w, h);
222
223     webview = evas_object_name_find(ecore_evas_get(ee), "browser");
224     evas_object_move(webview, 10, 10);
225     evas_object_resize(webview, w - 20, h - 20);
226 }
227
228 static void
229 title_set(Ecore_Evas *ee, const char *title, int progress)
230 {
231     const char *appname = "EFL Test Launcher";
232     const char *separator = " - ";
233     char label[4096];
234     int size;
235
236     if (!title || !strcmp(title, "")) {
237         ecore_evas_title_set(ee, appname);
238         return;
239     }
240
241     if (progress < 100)
242         size = snprintf(label, sizeof(label), "%s (%d%%)%s%s", title, progress, separator, appname);
243     else
244         size = snprintf(label, sizeof(label), "%s %s%s", title, separator, appname);
245
246     if (size >= (int)sizeof(label))
247         return;
248
249     ecore_evas_title_set(ee, label);
250 }
251
252 static void
253 on_title_changed(void *user_data, Evas_Object *webview, void *event_info)
254 {
255     ELauncher *app = (ELauncher *)user_data;
256     const char *title = (const char *)event_info;
257
258     title_set(app->ee, title, 100);
259 }
260
261 static void
262 on_progress(void *user_data, Evas_Object *webview, void *event_info)
263 {
264     ELauncher *app = (ELauncher *)user_data;
265     double *progress = (double *)event_info;
266
267     title_set(app->ee, ewk_view_title_get(app->browser), *progress * 100);
268 }
269
270 static void
271 on_load_finished(void *user_data, Evas_Object *webview, void *event_info)
272 {
273     const Ewk_Frame_Load_Error *err = (const Ewk_Frame_Load_Error *)event_info;
274
275     if (!err)
276         info("Succeeded loading page.\n");
277     else if (err->is_cancellation)
278         info("Load was cancelled.\n");
279     else
280         info("Failed loading page: %d %s \"%s\", url=%s\n",
281              err->code, err->domain, err->description, err->failing_url);
282
283     currentZoom = ewk_view_zoom_get(webview);
284     currentZoomLevel = nearest_zoom_level_get(currentZoom);
285     info("WebCore Zoom=%f, currentZoomLevel=%d\n", currentZoom, currentZoomLevel);
286 }
287
288 static void
289 on_load_error(void *user_data, Evas_Object *webview, void *event_info)
290 {
291     const Ewk_Frame_Load_Error *err = (const Ewk_Frame_Load_Error *)event_info;
292     char message[1024];
293     snprintf(message, 1024, "<html><body><div style=\"color:#ff0000\">ERROR!</div><br><div>Code: %d<br>Domain: %s<br>Description: %s<br>URL: %s</div></body</html>",
294              err->code, err->domain, err->description, err->failing_url);
295     ewk_frame_contents_set(err->frame, message, 0, "text/html", "UTF-8", err->failing_url);
296 }
297
298 static void
299 on_toolbars_visible_set(void* user_data, Evas_Object* webview, void* event_info)
300 {
301     Eina_Bool *visible = (Eina_Bool *)event_info;
302     if (*visible) {
303         info("Toolbars visible changed: show");
304         windowProperties.toolbarsVisible = EINA_TRUE;
305     } else {
306         info("Toolbars visible changed: hide");
307         windowProperties.toolbarsVisible = EINA_FALSE;
308     }
309 }
310
311 static void
312 on_toolbars_visible_get(void* user_data, Evas_Object* webview, void* event_info)
313 {
314     Eina_Bool *visible = (Eina_Bool *)event_info;
315     *visible = windowProperties.toolbarsVisible;
316 }
317
318 static void
319 on_statusbar_visible_set(void* user_data, Evas_Object* webview, void* event_info)
320 {
321     Eina_Bool *visible = (Eina_Bool *)event_info;
322     if (*visible) {
323         info("Statusbar visible changed: show");
324         windowProperties.statusbarVisible = EINA_TRUE;
325     } else {
326         info("Statusbar visible changed: hide");
327         windowProperties.statusbarVisible = EINA_FALSE;
328     }
329 }
330
331 static void
332 on_statusbar_visible_get(void* user_data, Evas_Object* webview, void* event_info)
333 {
334     Eina_Bool *visible = (Eina_Bool *)event_info;
335     *visible = windowProperties.statusbarVisible;
336 }
337
338 static void
339 on_scrollbars_visible_set(void* user_data, Evas_Object* webview, void* event_info)
340 {
341     Eina_Bool *visible = (Eina_Bool *)event_info;
342     if (*visible) {
343         info("Scrollbars visible changed: show");
344         windowProperties.scrollbarsVisible = EINA_TRUE;
345     } else {
346         info("Scrollbars visible changed: hide");
347         windowProperties.scrollbarsVisible = EINA_FALSE;
348     }
349 }
350
351 static void
352 on_scrollbars_visible_get(void* user_data, Evas_Object* webview, void* event_info)
353 {
354     Eina_Bool *visible = (Eina_Bool *)event_info;
355     *visible = windowProperties.scrollbarsVisible;
356 }
357
358 static void
359 on_menubar_visible_set(void* user_data, Evas_Object* webview, void* event_info)
360 {
361     Eina_Bool *visible = (Eina_Bool *)event_info;
362     if (*visible) {
363         info("Menubar visible changed: show");
364         windowProperties.menubarVisible = EINA_TRUE;
365     } else {
366         info("Menubar visible changed: hide");
367         windowProperties.menubarVisible = EINA_FALSE;
368     }
369 }
370
371 static void
372 on_menubar_visible_get(void* user_data, Evas_Object* webview, void* event_info)
373 {
374     Eina_Bool *visible = (Eina_Bool *)event_info;
375     *visible = windowProperties.menubarVisible;
376 }
377
378 static void
379 on_tooltip_text_set(void* user_data, Evas_Object* webview, void* event_info)
380 {
381     const char *text = (const char *)event_info;
382     if (text && *text != '\0')
383         info("%s\n", text);
384 }
385
386 static void
387 on_inputmethod_changed(void* user_data, Evas_Object* webview, void* event_info)
388 {
389     Eina_Bool active = (Eina_Bool)(long)event_info;
390     unsigned int imh;
391     info("Keyboard changed: %d\n", active);
392
393     if (!active)
394         return;
395
396     imh = ewk_view_imh_get(webview);
397     info("    Keyboard flags: %#.2x\n", imh);
398
399 }
400
401 static void
402 on_mouse_down(void* data, Evas* e, Evas_Object* webview, void* event_info)
403 {
404     Evas_Event_Mouse_Down *ev = (Evas_Event_Mouse_Down*) event_info;
405     if (ev->button == 2)
406         evas_object_focus_set(webview, !evas_object_focus_get(webview));
407 }
408
409 static void
410 on_focus_out(void *data, Evas *e, Evas_Object *obj, void *event_info)
411 {
412     info("the webview lost keyboard focus\n");
413 }
414
415 static void
416 on_focus_in(void *data, Evas *e, Evas_Object *obj, void *event_info)
417 {
418     info("the webview gained keyboard focus\n");
419 }
420
421 static void
422 on_key_down(void *data, Evas *e, Evas_Object *obj, void *event_info)
423 {
424     Evas_Event_Key_Down *ev = (Evas_Event_Key_Down*) event_info;
425     ELauncher *app = data;
426     static const char *encodings[] = {
427         "ISO-8859-1",
428         "UTF-8",
429         NULL
430     };
431     static int currentEncoding = -1;
432
433     if (!strcmp(ev->key, "Escape")) {
434         closeWindow(app->ee);
435     } else if (!strcmp(ev->key, "F1")) {
436         info("Back (F1) was pressed\n");
437         if (ewk_view_back_possible(obj)) {
438             Ewk_History *history = ewk_view_history_get(obj);
439             Eina_List *list = ewk_history_back_list_get(history);
440             print_history(list);
441             ewk_history_item_list_free(list);
442             ewk_view_back(obj);
443         } else
444             info("Back ignored: No back history\n");
445     } else if (!strcmp(ev->key, "F2")) {
446         info("Forward (F2) was pressed\n");
447         if (ewk_view_forward_possible(obj)) {
448             Ewk_History *history = ewk_view_history_get(obj);
449             Eina_List *list = ewk_history_forward_list_get(history);
450             print_history(list);
451             ewk_history_item_list_free(list);
452             ewk_view_forward(obj);
453         } else
454             info("Forward ignored: No forward history\n");
455     } else if (!strcmp(ev->key, "F3")) {
456         currentEncoding++;
457         currentEncoding %= (sizeof(encodings) / sizeof(encodings[0]));
458         info("Set encoding (F3) pressed. New encoding to %s", encodings[currentEncoding]);
459         ewk_view_setting_encoding_custom_set(obj, encodings[currentEncoding]);
460     } else if (!strcmp(ev->key, "F4")) {
461         Evas_Object *frame = ewk_view_frame_main_get(obj);
462         Evas_Coord x, y;
463         Ewk_Hit_Test *ht;
464
465         evas_pointer_canvas_xy_get(evas_object_evas_get(obj), &x, &y);
466         ht = ewk_frame_hit_test_new(frame, x, y);
467         if (!ht)
468             printf("No hit test returned for point %d,%d\n", x, y);
469         else {
470             printf("Hit test for point %d,%d\n"
471                    "  pos=%3d,%3d\n"
472                    "  bounding_box=%d,%d + %dx%d\n"
473                    "  title='%s'\n"
474                    "  alternate_text='%s'\n"
475                    "  frame=%p (%s)\n"
476                    "  link {\n"
477                    "    text='%s'\n"
478                    "    url='%s'\n"
479                    "    title='%s'\n"
480                    "    target frame=%p (%s)\n"
481                    "  }\n"
482                    "context:\n"
483                    "%s"
484                    "%s"
485                    "%s"
486                    "%s"
487                    "%s\n",
488                    x, y,
489                    ht->x, ht->y,
490                    ht->bounding_box.x, ht->bounding_box.y, ht->bounding_box.w, ht->bounding_box.h,
491                    ht->title,
492                    ht->alternate_text,
493                    ht->frame, evas_object_name_get(ht->frame),
494                    ht->link.text,
495                    ht->link.url,
496                    ht->link.title,
497                    ht->link.target_frame, evas_object_name_get(ht->link.target_frame),
498                    ht->context & EWK_HIT_TEST_RESULT_CONTEXT_LINK ? "  LINK\n" : "",
499                    ht->context & EWK_HIT_TEST_RESULT_CONTEXT_IMAGE ? "  IMAGE\n" : "",
500                    ht->context & EWK_HIT_TEST_RESULT_CONTEXT_MEDIA ? "   MEDIA\n" : "",
501                    ht->context & EWK_HIT_TEST_RESULT_CONTEXT_SELECTION ? "  SELECTION\n" : "",
502                    ht->context & EWK_HIT_TEST_RESULT_CONTEXT_EDITABLE ? "  EDITABLE" : "");
503             ewk_frame_hit_test_free(ht);
504         }
505
506     } else if (!strcmp(ev->key, "F5")) {
507         info("Reload (F5) was pressed, reloading.\n");
508         ewk_view_reload(obj);
509     } else if (!strcmp(ev->key, "F6")) {
510         info("Stop (F6) was pressed, stop loading.\n");
511         ewk_view_stop(obj);
512     } else if (!strcmp(ev->key, "F12")) {
513         Eina_Bool status = ewk_view_setting_spatial_navigation_get(obj);
514         ewk_view_setting_spatial_navigation_set(obj, !status);
515         info("Command::keyboard navigation toggle\n");
516     } else if (!strcmp(ev->key, "F7")) {
517         info("Zoom out (F7) was pressed.\n");
518         if (currentZoomLevel > MIN_ZOOM_LEVEL && zoom_level_set(obj, currentZoomLevel - 1))
519             currentZoomLevel--;
520     } else if (!strcmp(ev->key, "F8")) {
521         info("Zoom in (F8) was pressed.\n");
522         if (currentZoomLevel < MAX_ZOOM_LEVEL && zoom_level_set(obj, currentZoomLevel + 1))
523             currentZoomLevel++;
524     } else if (!strcmp(ev->key, "F9")) {
525         info("Create new window (F9) was pressed.\n");
526         Eina_Rectangle geometry = {0, 0, 0, 0};
527         browserCreate("http://www.google.com",
528                        app->theme, app->userAgent, geometry, app-> backingStore,
529                        NULL, app->isFlattening, 0, NULL);
530     } else if (!strcmp(ev->key, "F10")) {
531         Evas_Coord x, y, w, h;
532         Evas_Object *frame = ewk_view_frame_main_get(obj);
533         float zoom = zoomLevels[currentZoomLevel] / 100.0;
534
535         ewk_frame_visible_content_geometry_get(frame, EINA_FALSE, &x, &y, &w, &h);
536         x -= w;
537         y -= h;
538         w *= 4;
539         h *= 4;
540         info("Pre-render %d,%d + %dx%d\n", x, y, w, h);
541         ewk_view_pre_render_region(obj, x, y, w, h, zoom);
542     } else if (!strcmp(ev->key, "F11")) {
543         info("Pre-render 1 extra column/row with current zoom");
544         ewk_view_pre_render_relative_radius(obj, 1);
545     } else if (!strcmp(ev->key, "d")) {
546         info("Render suspended");
547         ewk_view_disable_render(obj);
548     } else if (!strcmp(ev->key, "e")) {
549         info("Render resumed");
550         ewk_view_enable_render(obj);
551     } else if (!strcmp(ev->key, "Insert")) {
552         info("Pre-rendering start");
553         ewk_view_pre_render_start(obj);
554     }
555 }
556
557 static void
558 on_browser_del(void *data, Evas *evas, Evas_Object *browser, void *event)
559 {
560     ELauncher *app = (ELauncher*) data;
561
562     evas_object_event_callback_del(app->browser, EVAS_CALLBACK_KEY_DOWN, on_key_down);
563     evas_object_event_callback_del(app->browser, EVAS_CALLBACK_MOUSE_DOWN, on_mouse_down);
564     evas_object_event_callback_del(app->browser, EVAS_CALLBACK_FOCUS_IN, on_focus_in);
565     evas_object_event_callback_del(app->browser, EVAS_CALLBACK_FOCUS_OUT, on_focus_out);
566     evas_object_event_callback_del(app->browser, EVAS_CALLBACK_DEL, on_browser_del);
567 }
568
569 static int
570 quit(Eina_Bool success, const char *msg)
571 {
572     edje_shutdown();
573     ecore_evas_shutdown();
574     ecore_file_shutdown();
575
576     if (msg)
577         fputs(msg, (success) ? stdout : stderr);
578
579     if (themePath) {
580         free(themePath);
581         themePath = NULL;
582     }
583
584     if (!success)
585         return EXIT_FAILURE;
586
587     return EXIT_SUCCESS;
588 }
589
590 static int
591 browserCreate(const char *url, const char *theme, const char *userAgent, Eina_Rectangle geometry, const char *engine, const char *backingStore, unsigned char isFlattening, unsigned char isFullscreen, const char *databasePath)
592 {
593     if ((geometry.w <= 0) && (geometry.h <= 0)) {
594         geometry.w = DEFAULT_WIDTH;
595         geometry.h = DEFAULT_HEIGHT;
596     }
597
598     ELauncher *app = (ELauncher*) malloc(sizeof(ELauncher));
599     if (!app)
600         return quit(EINA_FALSE, "ERROR: could not create EWebLauncher window\n");
601
602     app->ee = ecore_evas_new(engine, 0, 0, geometry.w, geometry.h, NULL);
603
604     if (!app->ee)
605         return quit(EINA_FALSE, "ERROR: could not construct evas-ecore\n");
606
607     if (isFullscreen)
608         ecore_evas_fullscreen_set(app->ee, EINA_TRUE);
609
610     ecore_evas_title_set(app->ee, "EFL Test Launcher");
611     ecore_evas_callback_resize_set(app->ee, on_ecore_evas_resize);
612     ecore_evas_callback_delete_request_set(app->ee, closeWindow);
613
614     app->evas = ecore_evas_get(app->ee);
615
616     if (!app->evas)
617         return quit(EINA_FALSE, "ERROR: could not get evas from evas-ecore\n");
618
619     app->theme = theme;
620     app->userAgent = userAgent;
621     app->backingStore = backingStore;
622     app->isFlattening = isFlattening;
623
624     app->bg = evas_object_rectangle_add(app->evas);
625     evas_object_name_set(app->bg, "bg");
626     evas_object_color_set(app->bg, 255, 0, 255, 255);
627     evas_object_move(app->bg, 0, 0);
628     evas_object_resize(app->bg, geometry.w, geometry.h);
629     evas_object_layer_set(app->bg, EVAS_LAYER_MIN);
630     evas_object_show(app->bg);
631
632     if (backingStore && !strcasecmp(backingStore, "tiled")) {
633         app->browser = ewk_view_tiled_add(app->evas);
634         info("backing store: tiled\n");
635     } else {
636         app->browser = ewk_view_single_add(app->evas);
637         info("backing store: single\n");
638     }
639
640     ewk_view_theme_set(app->browser, theme);
641     if (userAgent)
642         ewk_view_setting_user_agent_set(app->browser, userAgent);
643     ewk_view_setting_local_storage_database_path_set(app->browser, databasePath);
644     ewk_view_setting_enable_frame_flattening_set(app->browser, isFlattening);
645     
646     evas_object_name_set(app->browser, "browser");
647
648     evas_object_smart_callback_add(app->browser, "title,changed", on_title_changed, app);
649     evas_object_smart_callback_add(app->browser, "load,progress", on_progress, app);
650     evas_object_smart_callback_add(app->browser, "load,finished", on_load_finished, app);
651     evas_object_smart_callback_add(app->browser, "load,error", on_load_error, app);
652
653     evas_object_smart_callback_add(app->browser, "toolbars,visible,set", on_toolbars_visible_set, app);
654     evas_object_smart_callback_add(app->browser, "toolbars,visible,get", on_toolbars_visible_get, app);
655     evas_object_smart_callback_add(app->browser, "statusbar,visible,set", on_statusbar_visible_set, app);
656     evas_object_smart_callback_add(app->browser, "statusbar,visible,get", on_statusbar_visible_get, app);
657     evas_object_smart_callback_add(app->browser, "scrollbars,visible,set", on_scrollbars_visible_set, app);
658     evas_object_smart_callback_add(app->browser, "scrollbars,visible,get", on_scrollbars_visible_get, app);
659     evas_object_smart_callback_add(app->browser, "menubar,visible,set", on_menubar_visible_set, app);
660     evas_object_smart_callback_add(app->browser, "menubar,visible,get", on_menubar_visible_get, app);
661     evas_object_smart_callback_add(app->browser, "tooltip,text,set", on_tooltip_text_set, app);
662     evas_object_smart_callback_add(app->browser, "inputmethod,changed", on_inputmethod_changed, app);
663
664 /*     ewk_callback_resize_requested_add(app->browser, on_resize_requested, app->ee); */
665
666     evas_object_event_callback_add(app->browser, EVAS_CALLBACK_KEY_DOWN, on_key_down, app);
667     evas_object_event_callback_add(app->browser, EVAS_CALLBACK_MOUSE_DOWN, on_mouse_down, app);
668     evas_object_event_callback_add(app->browser, EVAS_CALLBACK_FOCUS_IN, on_focus_in, app);
669     evas_object_event_callback_add(app->browser, EVAS_CALLBACK_FOCUS_OUT, on_focus_out, app);
670     evas_object_event_callback_add(app->browser, EVAS_CALLBACK_DEL, on_browser_del, app);
671
672     evas_object_move(app->browser, 10, 10);
673     evas_object_resize(app->browser, geometry.w - 20, geometry.h - 20);
674
675     if (url && (url[0] != '\0'))
676         ewk_view_uri_set(app->browser, url);
677
678     evas_object_show(app->browser);
679     ecore_evas_show(app->ee);
680
681     evas_object_focus_set(app->browser, EINA_TRUE);
682
683     windows = eina_list_append(windows, app);
684
685     return 1;
686 }
687
688 static void
689 browserDestroy(Ecore_Evas *ee)
690 {
691     ecore_evas_free(ee);
692     if (!eina_list_count(windows))
693         ecore_main_loop_quit();
694 }
695
696 static void
697 closeWindow(Ecore_Evas *ee)
698 {
699     Eina_List *l;
700     void *app;
701     EINA_LIST_FOREACH(windows, l, app)
702     {
703         if (((ELauncher*) app)->ee == ee)
704             break;
705     }
706     windows = eina_list_remove(windows, app);
707     browserDestroy(ee);
708     free(app);
709 }
710
711 static Eina_Bool
712 main_signal_exit(void *data, int ev_type, void *ev)
713 {
714     ELauncher *app;
715     while (windows) {
716         app = (ELauncher*) eina_list_data_get(windows);
717         ecore_evas_free(app->ee);
718         windows = eina_list_remove(windows, app);
719     }
720     if (!eina_list_count(windows))
721         ecore_main_loop_quit();
722     return EINA_TRUE;
723 }
724
725 static char *
726 findThemePath(const char *theme)
727 {
728     const char *defaultTheme = DATA_DIR"/default.edj";
729     char *rpath;
730     struct stat st;
731
732     if (!theme)
733         theme = defaultTheme;
734
735     rpath = ecore_file_realpath(theme);
736     if (!strlen(rpath) || stat(rpath, &st)) {
737         free(rpath);
738         return NULL;
739     }
740
741     return rpath;
742 }
743
744 int
745 main(int argc, char *argv[])
746 {
747     const char *default_url = "http://www.google.com/";
748
749     Eina_Rectangle geometry = {0, 0, 0, 0};
750     char *url = NULL;
751     char *userAgent = NULL;
752     const char *tmp;
753     const char *proxyUri;
754     char path[PATH_MAX];
755
756     char *engine = NULL;
757     char *theme = NULL;
758     char *backingStore = (char *)backingStores[1];
759
760     unsigned char quitOption = 0;
761     unsigned char isFlattening = 0;
762     unsigned char isFullscreen = 0;
763     int args;
764
765     Ecore_Getopt_Value values[] = {
766         ECORE_GETOPT_VALUE_STR(engine),
767         ECORE_GETOPT_VALUE_BOOL(quitOption),
768         ECORE_GETOPT_VALUE_STR(backingStore),
769         ECORE_GETOPT_VALUE_BOOL(isFlattening),
770         ECORE_GETOPT_VALUE_BOOL(isFullscreen),
771         ECORE_GETOPT_VALUE_PTR_CAST(geometry),
772         ECORE_GETOPT_VALUE_STR(theme),
773         ECORE_GETOPT_VALUE_STR(userAgent),
774         ECORE_GETOPT_VALUE_INT(verbose),
775         ECORE_GETOPT_VALUE_BOOL(quitOption),
776         ECORE_GETOPT_VALUE_BOOL(quitOption),
777         ECORE_GETOPT_VALUE_BOOL(quitOption),
778         ECORE_GETOPT_VALUE_BOOL(quitOption),
779         ECORE_GETOPT_VALUE_NONE
780     };
781
782     if (!ecore_evas_init())
783         return EXIT_FAILURE;
784
785     if (!edje_init()) {
786         ecore_evas_shutdown();
787         return EXIT_FAILURE;
788     }
789
790     if (!ecore_file_init()) {
791         edje_shutdown();
792         ecore_evas_shutdown();
793         return EXIT_FAILURE;
794     }
795
796     ecore_app_args_set(argc, (const char**) argv);
797     args = ecore_getopt_parse(&options, values, argc, argv);
798
799     if (args < 0)
800        return quit(EINA_FALSE, "ERROR: could not parse options.\n");
801
802     if (quitOption)
803         return quit(EINA_TRUE, NULL);
804
805     if (args < argc)
806         url = argv[args];
807     else
808         url = (char*) default_url;
809
810     themePath = findThemePath(theme);
811     if (!themePath)
812         return quit(EINA_FALSE, "ERROR: could not find theme.\n");
813
814     ewk_init();
815     tmp = getenv("TMPDIR");
816     if (!tmp)
817         tmp = "/tmp";
818     snprintf(path, sizeof(path), "%s/.ewebkit-%u", tmp, getuid());
819     if (!ecore_file_mkpath(path))
820         return quit(EINA_FALSE, "ERROR: could not create settings database directory.\n");
821
822     ewk_settings_icon_database_path_set(path);
823     ewk_settings_web_database_path_set(path);
824
825     proxyUri = getenv("http_proxy");
826     if (proxyUri)
827         ewk_network_proxy_uri_set(proxyUri);
828
829     browserCreate(url, themePath, userAgent, geometry, engine, backingStore, isFlattening, isFullscreen, path);
830     ecore_event_handler_add(ECORE_EVENT_SIGNAL_EXIT, main_signal_exit, &windows);
831
832     ecore_main_loop_begin();
833
834     ewk_shutdown();
835
836     return quit(EINA_TRUE, NULL);
837 }