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