/* * Copyright (C) 2008 INdT - Instituto Nokia de Tecnologia * Copyright (C) 2009, 2010 ProFUSION embedded systems * Copyright (C) 2009, 2010, 2011 Samsung Electronics * Copyright (C) 2012 Intel Corporation * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "EWebKit.h" #include "url_bar.h" #include "url_utils.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define DEFAULT_WIDTH 800 #define DEFAULT_HEIGHT 600 #define DEFAULT_ZOOM_INIT 1.0 #define info(format, args...) \ do { \ if (verbose) \ printf(format, ##args); \ } while (0) #define MIN_ZOOM_LEVEL 0 #define DEFAULT_ZOOM_LEVEL 5 #define MAX_ZOOM_LEVEL 13 static int currentZoomLevel = DEFAULT_ZOOM_LEVEL; static float currentZoom = 1.0; // the zoom values are chosen to be like in Mozilla Firefox 3 static int zoomLevels[] = {30, 50, 67, 80, 90, 100, 110, 120, 133, 150, 170, 200, 240, 300}; static int verbose = 0; static Eina_List *windows = NULL; static char *themePath = NULL; static const char *backingStores[] = { "tiled", "single", NULL }; typedef struct _Window_Properties { Eina_Bool toolbarsVisible:1; Eina_Bool statusbarVisible:1; Eina_Bool scrollbarsVisible:1; Eina_Bool menubarVisible:1; } Window_Properties; Window_Properties windowProperties = { /* Pretend we have them and they are initially visible */ EINA_TRUE, EINA_TRUE, EINA_TRUE, EINA_TRUE }; static const Ecore_Getopt options = { "EWebLauncher", "%prog [options] [url]", "0.0.1", "(C)2008 INdT (The Nokia Technology Institute)\n" "(C)2009, 2010 ProFUSION embedded systems\n" "(C)2009, 2010, 2011 Samsung Electronics\n" "(C)2012 Intel Corporation\n", "GPL", "Test Web Browser using the Enlightenment Foundation Libraries of WebKit", EINA_TRUE, { ECORE_GETOPT_STORE_STR ('e', "engine", "ecore-evas engine to use."), ECORE_GETOPT_CALLBACK_NOARGS ('E', "list-engines", "list ecore-evas engines.", ecore_getopt_callback_ecore_evas_list_engines, NULL), ECORE_GETOPT_CHOICE ('b', "backing-store", "choose backing store to use.", backingStores), ECORE_GETOPT_STORE_DEF_BOOL ('c', "encoding-detector", "enable/disable encoding detector", 0), ECORE_GETOPT_STORE_DEF_BOOL ('f', "flattening", "frame flattening.", 0), ECORE_GETOPT_STORE_DEF_BOOL ('F', "fullscreen", "fullscreen mode.", 0), ECORE_GETOPT_CALLBACK_ARGS ('g', "geometry", "geometry to use in x:y:w:h form.", "X:Y:W:H", ecore_getopt_callback_geometry_parse, NULL), ECORE_GETOPT_STORE_STR ('t', "theme", "path to read the theme file from."), ECORE_GETOPT_STORE_DEF_BOOL ('T', "tiled-backing-store", "enable/disable WebCore's tiled backingstore(ewk_view_single only)", 0), ECORE_GETOPT_STORE_STR ('U', "user-agent", "custom user agent string to use."), ECORE_GETOPT_COUNT ('v', "verbose", "be more verbose."), ECORE_GETOPT_VERSION ('V', "version"), ECORE_GETOPT_COPYRIGHT ('R', "copyright"), ECORE_GETOPT_LICENSE ('L', "license"), ECORE_GETOPT_HELP ('h', "help"), ECORE_GETOPT_SENTINEL } }; typedef struct _User_Arguments { char *engine; Eina_Bool quitOption; char *backingStore; Eina_Bool enableEncodingDetector; Eina_Bool enableTiledBackingStore; Eina_Bool isFlattening; Eina_Bool isFullscreen; Eina_Rectangle geometry; char *theme; char *userAgent; char *databasePath; } User_Arguments; typedef struct _ELauncher { Ecore_Evas *ee; Evas *evas; Evas_Object *browser; Url_Bar *url_bar; User_Arguments *userArgs; } ELauncher; static void windowDestroy(Ecore_Evas *ee); static void closeWindow(Ecore_Evas *ee); static int browserCreate(const char *url, User_Arguments *userArgs); static int webInspectorCreate(ELauncher *appBrowser); static ELauncher *windowCreate(User_Arguments *userArgs); static ELauncher * find_app_from_ee(Ecore_Evas *ee) { Eina_List *l; void *data; EINA_LIST_FOREACH(windows, l, data) { ELauncher *app = (ELauncher *) data; if (app->ee == ee) return app; } return NULL; } static void print_history(Eina_List *list) { Eina_List *l; void *d; if (!verbose) return; printf("Session history contains:\n"); EINA_LIST_FOREACH(list, l, d) { Ewk_History_Item *item = (Ewk_History_Item*)d; cairo_surface_t *cs = ewk_history_item_icon_surface_get(item); char buf[PATH_MAX]; int s = snprintf(buf, sizeof(buf), "/tmp/favicon-%s.png", ewk_history_item_uri_original_get(item)); for (s--; s >= (int)sizeof("/tmp/favicon-"); s--) { if (!isalnum(buf[s]) && buf[s] != '.') buf[s] = '_'; } cs = ewk_history_item_icon_surface_get(item); if (cs && cairo_surface_status(cs) == CAIRO_STATUS_SUCCESS) cairo_surface_write_to_png(cs, buf); else buf[0] = '\0'; printf("* '%s' title='%s' icon='%s'\n", ewk_history_item_uri_original_get(item), ewk_history_item_title_get(item), buf); } } static int nearest_zoom_level_get(float factor) { int i, intFactor = (int)(factor * 100.0); for (i = 0; zoomLevels[i] <= intFactor; i++) { } printf("factor=%f, intFactor=%d, zoomLevels[%d]=%d, zoomLevels[%d]=%d\n", factor, intFactor, i-1, zoomLevels[i-1], i, zoomLevels[i]); if (intFactor - zoomLevels[i-1] < zoomLevels[i] - intFactor) return i - 1; return i; } static Eina_Bool zoom_level_set(Evas_Object *webview, int level) { float factor = ((float) zoomLevels[level]) / 100.0; Evas_Coord ox, oy, mx, my, cx, cy; evas_pointer_canvas_xy_get(evas_object_evas_get(webview), &mx, &my); evas_object_geometry_get(webview, &ox, &oy, NULL, NULL); cx = mx - ox; cy = my - oy; return ewk_view_zoom_animated_set(webview, factor, 0.5, cx, cy); } static void on_browser_ecore_evas_resize(Ecore_Evas *ee) { ELauncher *app; Evas_Object *webview; int w, h; ecore_evas_geometry_get(ee, NULL, NULL, &w, &h); /* Resize URL bar */ app = find_app_from_ee(ee); url_bar_width_set(app->url_bar, w); webview = evas_object_name_find(ecore_evas_get(ee), "browser"); evas_object_move(webview, 0, URL_BAR_HEIGHT); evas_object_resize(webview, w, h - URL_BAR_HEIGHT); } static void on_inspector_ecore_evas_resize(Ecore_Evas *ee) { Evas_Object *webview; int w, h; ecore_evas_geometry_get(ee, NULL, NULL, &w, &h); webview = evas_object_name_find(ecore_evas_get(ee), "inspector"); evas_object_move(webview, 0, 0); evas_object_resize(webview, w, h); } static void title_set(Ecore_Evas *ee, const Ewk_Text_With_Direction *title, int progress) { const char *appname = "EFL Test Launcher"; const char *separator = " - "; char label[4096]; int size; if (!title || !title->string || !strcmp(title->string, "")) { ecore_evas_title_set(ee, appname); return; } if (progress < 100) size = snprintf(label, sizeof(label), "%s (%d%%)%s%s", title->string, progress, separator, appname); else size = snprintf(label, sizeof(label), "%s %s%s", title->string, separator, appname); if (size >= (int)sizeof(label)) return; ecore_evas_title_set(ee, label); } static void on_title_changed(void *user_data, Evas_Object *webview, void *event_info) { ELauncher *app = (ELauncher *)user_data; const Ewk_Text_With_Direction *title = (const Ewk_Text_With_Direction *)event_info; title_set(app->ee, title, 100); } static void on_progress(void *user_data, Evas_Object *webview, void *event_info) { ELauncher *app = (ELauncher *)user_data; double *progress = (double *)event_info; title_set(app->ee, ewk_view_title_get(app->browser), *progress * 100); } static void on_load_finished(void *user_data, Evas_Object *webview, void *event_info) { const Ewk_Frame_Load_Error *err = (const Ewk_Frame_Load_Error *)event_info; if (!err) info("Succeeded loading page.\n"); else if (err->is_cancellation) info("Load was cancelled.\n"); else info("Failed loading page: %d %s \"%s\", url=%s\n", err->code, err->domain, err->description, err->failing_url); currentZoom = ewk_view_zoom_get(webview); currentZoomLevel = nearest_zoom_level_get(currentZoom); info("WebCore Zoom=%f, currentZoomLevel=%d\n", currentZoom, currentZoomLevel); } static void on_load_error(void *user_data, Evas_Object *webview, void *event_info) { const Ewk_Frame_Load_Error *err = (const Ewk_Frame_Load_Error *)event_info; char message[1024]; snprintf(message, 1024, "
ERROR!

Code: %d
Domain: %s
Description: %s
URL: %s
", err->code, err->domain, err->description, err->failing_url); ewk_frame_contents_set(err->frame, message, 0, "text/html", "UTF-8", err->failing_url); } static void on_toolbars_visible_set(void* user_data, Evas_Object* webview, void* event_info) { Eina_Bool *visible = (Eina_Bool *)event_info; if (*visible) { info("Toolbars visible changed: show"); windowProperties.toolbarsVisible = EINA_TRUE; } else { info("Toolbars visible changed: hide"); windowProperties.toolbarsVisible = EINA_FALSE; } } static void on_toolbars_visible_get(void* user_data, Evas_Object* webview, void* event_info) { Eina_Bool *visible = (Eina_Bool *)event_info; *visible = windowProperties.toolbarsVisible; } static void on_statusbar_visible_set(void* user_data, Evas_Object* webview, void* event_info) { Eina_Bool *visible = (Eina_Bool *)event_info; if (*visible) { info("Statusbar visible changed: show"); windowProperties.statusbarVisible = EINA_TRUE; } else { info("Statusbar visible changed: hide"); windowProperties.statusbarVisible = EINA_FALSE; } } static void on_statusbar_visible_get(void* user_data, Evas_Object* webview, void* event_info) { Eina_Bool *visible = (Eina_Bool *)event_info; *visible = windowProperties.statusbarVisible; } static void on_scrollbars_visible_set(void* user_data, Evas_Object* webview, void* event_info) { Eina_Bool *visible = (Eina_Bool *)event_info; if (*visible) { info("Scrollbars visible changed: show"); windowProperties.scrollbarsVisible = EINA_TRUE; } else { info("Scrollbars visible changed: hide"); windowProperties.scrollbarsVisible = EINA_FALSE; } } static void on_scrollbars_visible_get(void* user_data, Evas_Object* webview, void* event_info) { Eina_Bool *visible = (Eina_Bool *)event_info; *visible = windowProperties.scrollbarsVisible; } static void on_menubar_visible_set(void* user_data, Evas_Object* webview, void* event_info) { Eina_Bool *visible = (Eina_Bool *)event_info; if (*visible) { info("Menubar visible changed: show"); windowProperties.menubarVisible = EINA_TRUE; } else { info("Menubar visible changed: hide"); windowProperties.menubarVisible = EINA_FALSE; } } static void on_menubar_visible_get(void* user_data, Evas_Object* webview, void* event_info) { Eina_Bool *visible = (Eina_Bool *)event_info; *visible = windowProperties.menubarVisible; } static void on_tooltip_text_set(void* user_data, Evas_Object* webview, void* event_info) { const char *text = (const char *)event_info; info("Tooltip is set: %s\n", text); } static void on_tooltip_text_unset(void* user_data, Evas_Object* webview, void* event_info) { info("Tooltip is unset\n"); } static void on_inputmethod_changed(void* user_data, Evas_Object* webview, void* event_info) { Eina_Bool active = (Eina_Bool)(long)event_info; unsigned int imh; info("Keyboard changed: %d\n", active); if (!active) return; imh = ewk_view_imh_get(webview); info(" Keyboard flags: %#.2x\n", imh); } static void on_url_changed(void* user_data, Evas_Object* webview, void* event_info) { ELauncher *app = (ELauncher *)user_data; url_bar_url_set(app->url_bar, ewk_view_uri_get(app->browser)); } static void on_mouse_down(void* data, Evas* e, Evas_Object* webview, void* event_info) { Evas_Event_Mouse_Down *ev = (Evas_Event_Mouse_Down *)event_info; if (ev->button == 1) evas_object_focus_set(webview, EINA_TRUE); else if (ev->button == 2) evas_object_focus_set(webview, !evas_object_focus_get(webview)); } static void on_focus_out(void *data, Evas *e, Evas_Object *obj, void *event_info) { info("the webview lost keyboard focus\n"); } static void on_focus_in(void *data, Evas *e, Evas_Object *obj, void *event_info) { info("the webview gained keyboard focus\n"); } static void on_key_down(void *data, Evas *e, Evas_Object *obj, void *event_info) { Evas_Event_Key_Down *ev = (Evas_Event_Key_Down*) event_info; ELauncher *app = data; static const char *encodings[] = { "ISO-8859-1", "UTF-8", NULL }; static int currentEncoding = -1; Eina_Bool ctrlPressed = evas_key_modifier_is_set(evas_key_modifier_get(e), "Control"); if (!strcmp(ev->key, "Escape")) { closeWindow(app->ee); } else if (!strcmp(ev->key, "F1")) { info("Back (F1) was pressed\n"); if (ewk_view_back_possible(obj)) { Ewk_History *history = ewk_view_history_get(obj); Eina_List *list = ewk_history_back_list_get(history); print_history(list); ewk_history_item_list_free(list); ewk_view_back(obj); } else info("Back ignored: No back history\n"); } else if (!strcmp(ev->key, "F2")) { info("Forward (F2) was pressed\n"); if (ewk_view_forward_possible(obj)) { Ewk_History *history = ewk_view_history_get(obj); Eina_List *list = ewk_history_forward_list_get(history); print_history(list); ewk_history_item_list_free(list); ewk_view_forward(obj); } else info("Forward ignored: No forward history\n"); } else if (!strcmp(ev->key, "F3")) { currentEncoding++; currentEncoding %= (sizeof(encodings) / sizeof(encodings[0])); info("Set encoding (F3) pressed. New encoding to %s", encodings[currentEncoding]); ewk_view_setting_encoding_custom_set(obj, encodings[currentEncoding]); } else if (!strcmp(ev->key, "F4")) { Evas_Object *frame = ewk_view_frame_main_get(obj); Evas_Coord x, y; Ewk_Hit_Test *ht; evas_pointer_canvas_xy_get(evas_object_evas_get(obj), &x, &y); ht = ewk_frame_hit_test_new(frame, x, y); if (!ht) printf("No hit test returned for point %d,%d\n", x, y); else { printf("Hit test for point %d,%d\n" " pos=%3d,%3d\n" " bounding_box=%d,%d + %dx%d\n" " title='%s'\n" " alternate_text='%s'\n" " frame=%p (%s)\n" " link {\n" " text='%s'\n" " url='%s'\n" " title='%s'\n" " target frame=%p (%s)\n" " }\n" "context:\n" "%s" "%s" "%s" "%s" "%s\n", x, y, ht->x, ht->y, ht->bounding_box.x, ht->bounding_box.y, ht->bounding_box.w, ht->bounding_box.h, ht->title.string, ht->alternate_text, ht->frame, evas_object_name_get(ht->frame), ht->link.text, ht->link.url, ht->link.title, ht->link.target_frame, evas_object_name_get(ht->link.target_frame), ht->context & EWK_HIT_TEST_RESULT_CONTEXT_LINK ? " LINK\n" : "", ht->context & EWK_HIT_TEST_RESULT_CONTEXT_IMAGE ? " IMAGE\n" : "", ht->context & EWK_HIT_TEST_RESULT_CONTEXT_MEDIA ? " MEDIA\n" : "", ht->context & EWK_HIT_TEST_RESULT_CONTEXT_SELECTION ? " SELECTION\n" : "", ht->context & EWK_HIT_TEST_RESULT_CONTEXT_EDITABLE ? " EDITABLE" : ""); ewk_frame_hit_test_free(ht); } } else if (!strcmp(ev->key, "F5")) { info("Reload (F5) was pressed, reloading.\n"); ewk_view_reload(obj); } else if (!strcmp(ev->key, "F6")) { info("Stop (F6) was pressed, stop loading.\n"); ewk_view_stop(obj); } else if (!strcmp(ev->key, "F12")) { Eina_Bool status = ewk_view_setting_spatial_navigation_get(obj); ewk_view_setting_spatial_navigation_set(obj, !status); info("Command::keyboard navigation toggle\n"); } else if ((!strcmp(ev->key, "minus") || !strcmp(ev->key, "KP_Subtract")) && ctrlPressed) { if (currentZoomLevel > MIN_ZOOM_LEVEL && zoom_level_set(obj, currentZoomLevel - 1)) currentZoomLevel--; info("Zoom out (Ctrl + '-') was pressed, zoom level became %.2f\n", zoomLevels[currentZoomLevel] / 100.0); } else if ((!strcmp(ev->key, "equal") || !strcmp(ev->key, "KP_Add")) && ctrlPressed) { if (currentZoomLevel < MAX_ZOOM_LEVEL && zoom_level_set(obj, currentZoomLevel + 1)) currentZoomLevel++; info("Zoom in (Ctrl + '+') was pressed, zoom level became %.2f\n", zoomLevels[currentZoomLevel] / 100.0); } else if (!strcmp(ev->key, "0") && ctrlPressed) { if (zoom_level_set(obj, DEFAULT_ZOOM_LEVEL)) currentZoomLevel = DEFAULT_ZOOM_LEVEL; info("Zoom to default (Ctrl + '0') was pressed, zoom level became %.2f\n", zoomLevels[currentZoomLevel] / 100.0); } else if (!strcmp(ev->key, "n") && ctrlPressed) { info("Create new window (Ctrl+n) was pressed.\n"); browserCreate("http://www.google.com", app->userArgs); } else if (!strcmp(ev->key, "g") && ctrlPressed ) { Evas_Coord x, y, w, h; Evas_Object *frame = ewk_view_frame_main_get(obj); float zoom = zoomLevels[currentZoomLevel] / 100.0; ewk_frame_visible_content_geometry_get(frame, EINA_FALSE, &x, &y, &w, &h); x -= w; y -= h; w *= 4; h *= 4; info("Pre-render %d,%d + %dx%d\n", x, y, w, h); ewk_view_pre_render_region(obj, x, y, w, h, zoom); } else if (!strcmp(ev->key, "r") && ctrlPressed) { info("Pre-render 1 extra column/row with current zoom"); ewk_view_pre_render_relative_radius(obj, 1); } else if (!strcmp(ev->key, "p") && ctrlPressed) { info("Pre-rendering start"); ewk_view_pre_render_start(obj); } else if (!strcmp(ev->key, "d") && ctrlPressed) { info("Render suspended"); ewk_view_disable_render(obj); } else if (!strcmp(ev->key, "e") && ctrlPressed) { info("Render resumed"); ewk_view_enable_render(obj); } else if (!strcmp(ev->key, "s") && ctrlPressed) { Evas_Object *frame = ewk_view_frame_main_get(obj); Ewk_Security_Origin *origin = ewk_frame_security_origin_get(frame); printf("Security origin information:\n" " protocol=%s\n" " host=%s\n" " port=%d\n" " web database quota=%" PRIu64 "\n", ewk_security_origin_protocol_get(origin), ewk_security_origin_host_get(origin), ewk_security_origin_port_get(origin), ewk_security_origin_web_database_quota_get(origin)); Eina_List *databaseList = ewk_security_origin_web_database_get_all(origin); Eina_List *listIterator = 0; Ewk_Web_Database *database; EINA_LIST_FOREACH(databaseList, listIterator, database) printf("Database information:\n" " name=%s\n" " display name=%s\n" " filename=%s\n" " expected size=%" PRIu64 "\n" " size=%" PRIu64 "\n", ewk_web_database_name_get(database), ewk_web_database_display_name_get(database), ewk_web_database_filename_get(database), ewk_web_database_expected_size_get(database), ewk_web_database_size_get(database)); ewk_security_origin_free(origin); ewk_web_database_list_free(databaseList); } else if (!strcmp(ev->key, "i") && ctrlPressed) { Evas_Object *inspector_view = ewk_view_inspector_view_get(obj); if (inspector_view) { info("Web Inspector close\n"); ewk_view_inspector_close(obj); } else { info("Web Inspector show\n"); ewk_view_inspector_show(obj); } } } static void on_browser_del(void *data, Evas *evas, Evas_Object *browser, void *event) { ELauncher *app = (ELauncher*) data; evas_object_event_callback_del(app->browser, EVAS_CALLBACK_KEY_DOWN, on_key_down); evas_object_event_callback_del(app->browser, EVAS_CALLBACK_MOUSE_DOWN, on_mouse_down); evas_object_event_callback_del(app->browser, EVAS_CALLBACK_FOCUS_IN, on_focus_in); evas_object_event_callback_del(app->browser, EVAS_CALLBACK_FOCUS_OUT, on_focus_out); evas_object_event_callback_del(app->browser, EVAS_CALLBACK_DEL, on_browser_del); } static void on_inspector_view_create(void *user_data, Evas_Object *webview, void *event_info) { ELauncher *app_browser = (ELauncher *)user_data; webInspectorCreate(app_browser); } static void on_inspector_view_close(void *user_data, Evas_Object *webview, void *event_info) { Eina_List *l; void *app; ELauncher *app_browser = (ELauncher *)user_data; Evas_Object *inspector_view = (Evas_Object *)event_info; ewk_view_inspector_view_set(app_browser->browser, NULL); EINA_LIST_FOREACH(windows, l, app) if (((ELauncher *)app)->browser == inspector_view) break; windows = eina_list_remove(windows, app); windowDestroy(((ELauncher *)app)->ee); free(app); } static void on_inspector_view_destroyed(Ecore_Evas *ee) { ELauncher *app; app = find_app_from_ee(ee); evas_object_smart_callback_call(app->browser, "inspector,view,destroy", NULL); } static int quit(Eina_Bool success, const char *msg) { edje_shutdown(); ecore_evas_shutdown(); ecore_file_shutdown(); if (msg) fputs(msg, (success) ? stdout : stderr); if (themePath) { free(themePath); themePath = NULL; } if (!success) return EXIT_FAILURE; return EXIT_SUCCESS; } static int browserCreate(const char *url, User_Arguments *userArgs) { ELauncher *appBrowser = windowCreate(userArgs); if (!appBrowser) return quit(EINA_FALSE, "ERROR: could not create a browser window\n"); ecore_evas_title_set(appBrowser->ee, "EFL Test Launcher"); ecore_evas_callback_resize_set(appBrowser->ee, on_browser_ecore_evas_resize); ecore_evas_callback_delete_request_set(appBrowser->ee, closeWindow); evas_object_name_set(appBrowser->browser, "browser"); evas_object_smart_callback_add(appBrowser->browser, "inputmethod,changed", on_inputmethod_changed, appBrowser); evas_object_smart_callback_add(appBrowser->browser, "inspector,view,close", on_inspector_view_close, appBrowser); evas_object_smart_callback_add(appBrowser->browser, "inspector,view,create", on_inspector_view_create, appBrowser); evas_object_smart_callback_add(appBrowser->browser, "load,error", on_load_error, appBrowser); evas_object_smart_callback_add(appBrowser->browser, "load,finished", on_load_finished, appBrowser); evas_object_smart_callback_add(appBrowser->browser, "load,progress", on_progress, appBrowser); evas_object_smart_callback_add(appBrowser->browser, "menubar,visible,get", on_menubar_visible_get, appBrowser); evas_object_smart_callback_add(appBrowser->browser, "menubar,visible,set", on_menubar_visible_set, appBrowser); evas_object_smart_callback_add(appBrowser->browser, "scrollbars,visible,get", on_scrollbars_visible_get, appBrowser); evas_object_smart_callback_add(appBrowser->browser, "scrollbars,visible,set", on_scrollbars_visible_set, appBrowser); evas_object_smart_callback_add(appBrowser->browser, "statusbar,visible,get", on_statusbar_visible_get, appBrowser); evas_object_smart_callback_add(appBrowser->browser, "statusbar,visible,set", on_statusbar_visible_set, appBrowser); evas_object_smart_callback_add(appBrowser->browser, "title,changed", on_title_changed, appBrowser); evas_object_smart_callback_add(appBrowser->browser, "toolbars,visible,get", on_toolbars_visible_get, appBrowser); evas_object_smart_callback_add(appBrowser->browser, "toolbars,visible,set", on_toolbars_visible_set, appBrowser); evas_object_smart_callback_add(appBrowser->browser, "tooltip,text,set", on_tooltip_text_set, appBrowser); evas_object_smart_callback_add(appBrowser->browser, "tooltip,text,unset", on_tooltip_text_unset, appBrowser); evas_object_smart_callback_add(appBrowser->browser, "uri,changed", on_url_changed, appBrowser); evas_object_event_callback_add(appBrowser->browser, EVAS_CALLBACK_DEL, on_browser_del, appBrowser); evas_object_event_callback_add(appBrowser->browser, EVAS_CALLBACK_FOCUS_IN, on_focus_in, appBrowser); evas_object_event_callback_add(appBrowser->browser, EVAS_CALLBACK_FOCUS_OUT, on_focus_out, appBrowser); evas_object_event_callback_add(appBrowser->browser, EVAS_CALLBACK_KEY_DOWN, on_key_down, appBrowser); evas_object_event_callback_add(appBrowser->browser, EVAS_CALLBACK_MOUSE_DOWN, on_mouse_down, appBrowser); ewk_view_setting_enable_developer_extras_set(appBrowser->browser, EINA_TRUE); appBrowser->url_bar = url_bar_add(appBrowser->browser, DEFAULT_WIDTH); evas_object_move(appBrowser->browser, 0, URL_BAR_HEIGHT); evas_object_resize(appBrowser->browser, userArgs->geometry.w, userArgs->geometry.h - URL_BAR_HEIGHT); ewk_view_uri_set(appBrowser->browser, url); evas_object_show(appBrowser->browser); ecore_evas_show(appBrowser->ee); evas_object_focus_set(appBrowser->browser, EINA_TRUE); return 1; } static int webInspectorCreate(ELauncher *appBrowser) { ELauncher *appInspector = windowCreate(appBrowser->userArgs); if (!appInspector) return quit(EINA_FALSE, "ERROR: could not create an inspector window\n"); ecore_evas_title_set(appInspector->ee, "Web Inspector"); ecore_evas_callback_resize_set(appInspector->ee, on_inspector_ecore_evas_resize); ecore_evas_callback_delete_request_set(appInspector->ee, on_inspector_view_destroyed); evas_object_name_set(appInspector->browser, "inspector"); evas_object_move(appInspector->browser, 0, 0); evas_object_resize(appInspector->browser, appInspector->userArgs->geometry.w, appInspector->userArgs->geometry.h); evas_object_show(appInspector->browser); ecore_evas_show(appInspector->ee); evas_object_focus_set(appInspector->browser, EINA_TRUE); ewk_view_inspector_view_set(appBrowser->browser, appInspector->browser); return 1; } static ELauncher * windowCreate(User_Arguments *userArgs) { ELauncher *app = (ELauncher *)malloc(sizeof(ELauncher)); if (!app) { quit(EINA_FALSE, "ERROR: could not create an ELauncher\n"); return NULL; } #if defined(WTF_USE_ACCELERATED_COMPOSITING) && defined(HAVE_ECORE_X) if (userArgs->engine) #endif app->ee = ecore_evas_new(userArgs->engine, 0, 0, userArgs->geometry.w, userArgs->geometry.h, NULL); #if defined(WTF_USE_ACCELERATED_COMPOSITING) && defined(HAVE_ECORE_X) else { const char* engine = "opengl_x11"; app->ee = ecore_evas_new(engine, 0, 0, userArgs->geometry.w, userArgs->geometry.h, NULL); } #endif if (!app->ee) { quit(EINA_FALSE, "ERROR: could not construct evas-ecore\n"); return NULL; } if (userArgs->isFullscreen) ecore_evas_fullscreen_set(app->ee, EINA_TRUE); app->evas = ecore_evas_get(app->ee); if (!app->evas) { quit(EINA_FALSE, "ERROR: could not get evas from evas-ecore\n"); return NULL; } if (userArgs->backingStore && !strcasecmp(userArgs->backingStore, "tiled")) { app->browser = ewk_view_tiled_add(app->evas); info("backing store: tiled\n"); } else { app->browser = ewk_view_single_add(app->evas); info("backing store: single\n"); ewk_view_setting_tiled_backing_store_enabled_set(app->browser, userArgs->enableTiledBackingStore); } ewk_view_theme_set(app->browser, themePath); if (userArgs->userAgent) ewk_view_setting_user_agent_set(app->browser, userArgs->userAgent); ewk_view_setting_local_storage_database_path_set(app->browser, userArgs->databasePath); ewk_view_setting_enable_frame_flattening_set(app->browser, userArgs->isFlattening); ewk_view_setting_encoding_detector_set(app->browser, userArgs->enableEncodingDetector); app->userArgs = userArgs; app->url_bar = NULL; windows = eina_list_append(windows, app); return app; } static void windowDestroy(Ecore_Evas *ee) { ecore_evas_free(ee); if (!eina_list_count(windows)) ecore_main_loop_quit(); } static void closeWindow(Ecore_Evas *ee) { ELauncher *app; app = find_app_from_ee(ee); ewk_view_inspector_close(app->browser); windows = eina_list_remove(windows, app); url_bar_del(app->url_bar); windowDestroy(ee); free(app); } static Eina_Bool main_signal_exit(void *data, int ev_type, void *ev) { ELauncher *app; while (windows) { app = (ELauncher*) eina_list_data_get(windows); ewk_view_inspector_close(app->browser); ecore_evas_free(app->ee); windows = eina_list_remove(windows, app); } if (!eina_list_count(windows)) ecore_main_loop_quit(); return EINA_TRUE; } static char * findThemePath(const char *theme) { const char *default_theme = THEME_DIR"/default.edj"; char *rpath; struct stat st; if (!theme) theme = default_theme; rpath = ecore_file_realpath(theme); if (!strlen(rpath) || stat(rpath, &st)) { free(rpath); return NULL; } return rpath; } int parseUserArguments(int argc, char *argv[], User_Arguments *userArgs) { int args; userArgs->engine = NULL; userArgs->quitOption = EINA_FALSE; userArgs->backingStore = (char *)backingStores[1]; userArgs->enableEncodingDetector = EINA_FALSE; userArgs->enableTiledBackingStore = EINA_FALSE; userArgs->isFlattening = EINA_FALSE; userArgs->isFullscreen = EINA_FALSE; userArgs->geometry.x = 0; userArgs->geometry.y = 0; userArgs->geometry.w = 0; userArgs->geometry.h = 0; userArgs->theme = NULL; userArgs->userAgent = NULL; Ecore_Getopt_Value values[] = { ECORE_GETOPT_VALUE_STR(userArgs->engine), ECORE_GETOPT_VALUE_BOOL(userArgs->quitOption), ECORE_GETOPT_VALUE_STR(userArgs->backingStore), ECORE_GETOPT_VALUE_BOOL(userArgs->enableEncodingDetector), ECORE_GETOPT_VALUE_BOOL(userArgs->isFlattening), ECORE_GETOPT_VALUE_BOOL(userArgs->isFullscreen), ECORE_GETOPT_VALUE_PTR_CAST(userArgs->geometry), ECORE_GETOPT_VALUE_STR(userArgs->theme), ECORE_GETOPT_VALUE_BOOL(userArgs->enableTiledBackingStore), ECORE_GETOPT_VALUE_STR(userArgs->userAgent), ECORE_GETOPT_VALUE_INT(verbose), ECORE_GETOPT_VALUE_BOOL(userArgs->quitOption), ECORE_GETOPT_VALUE_BOOL(userArgs->quitOption), ECORE_GETOPT_VALUE_BOOL(userArgs->quitOption), ECORE_GETOPT_VALUE_BOOL(userArgs->quitOption), ECORE_GETOPT_VALUE_NONE }; ecore_app_args_set(argc, (const char**) argv); args = ecore_getopt_parse(&options, values, argc, argv); themePath = findThemePath(userArgs->theme); if ((userArgs->geometry.w <= 0) || (userArgs->geometry.h <= 0)) { userArgs->geometry.w = DEFAULT_WIDTH; userArgs->geometry.h = DEFAULT_HEIGHT; } return args; } int main(int argc, char *argv[]) { const char *default_url = "http://www.google.com/"; const char *tmp; const char *proxyUri; char path[PATH_MAX]; int args; User_Arguments userArgs; if (!ecore_evas_init()) return EXIT_FAILURE; if (!edje_init()) { ecore_evas_shutdown(); return EXIT_FAILURE; } if (!ecore_file_init()) { edje_shutdown(); ecore_evas_shutdown(); return EXIT_FAILURE; } args = parseUserArguments(argc, argv, &userArgs); if (args < 0) return quit(EINA_FALSE, "ERROR: could not parse options.\n"); if (userArgs.quitOption) return quit(EINA_TRUE, NULL); if (!themePath) return quit(EINA_FALSE, "ERROR: could not find theme.\n"); ewk_init(); tmp = getenv("TMPDIR"); if (!tmp) tmp = "/tmp"; snprintf(path, sizeof(path), "%s/.ewebkit-%u", tmp, getuid()); if (!ecore_file_mkpath(path)) return quit(EINA_FALSE, "ERROR: could not create settings database directory.\n"); userArgs.databasePath = path; ewk_settings_icon_database_path_set(path); ewk_settings_web_database_path_set(path); proxyUri = getenv("http_proxy"); if (proxyUri) ewk_network_proxy_uri_set(proxyUri); if (args < argc) { char *url = url_from_user_input(argv[args]); browserCreate(url, &userArgs); free(url); } else browserCreate(default_url, &userArgs); ecore_event_handler_add(ECORE_EVENT_SIGNAL_EXIT, main_signal_exit, &windows); ecore_main_loop_begin(); ewk_shutdown(); return quit(EINA_TRUE, NULL); }