/* * Copyright (C) 2008 INdT - Instituto Nokia de Tecnologia * Copyright (C) 2009, 2010 ProFUSION embedded systems * Copyright (C) 2009, 2010, 2011 Samsung Electronics * * 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 <ctype.h> #include <Ecore.h> #include <Ecore_Evas.h> #include <Ecore_File.h> #include <Ecore_Getopt.h> #include <Ecore_X.h> #include <Edje.h> #include <Evas.h> #include <limits.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/stat.h> #include <sys/types.h> #include <unistd.h> #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", "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 ('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_STR ('U', "user-agent", "custom user agent string to use."), ECORE_GETOPT_STORE_DEF_BOOL ('S', "sudo-workaround", "Workaround mode for making Flash work with sudo.", 0), 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 _Viewport { int w; int h; float initScale; float minScale; float maxScale; float devicePixelRatio; Eina_Bool userScalable; } Viewport; typedef struct _ELauncher { Ecore_Evas *ee; Evas *evas; Evas_Object *bg; Evas_Object *browser; const char *theme; const char *userAgent; const char *backingStore; unsigned char isFlattening; Viewport viewport; } ELauncher; static void browserDestroy(Ecore_Evas *ee); static void closeWindow(Ecore_Evas *ee); 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); 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_ecore_evas_resize(Ecore_Evas *ee) { Evas_Object *webview; Evas_Object *bg; int w, h; ecore_evas_geometry_get(ee, NULL, NULL, &w, &h); bg = evas_object_name_find(ecore_evas_get(ee), "bg"); evas_object_move(bg, 0, 0); evas_object_resize(bg, w, h); webview = evas_object_name_find(ecore_evas_get(ee), "browser"); evas_object_move(webview, 10, 10); evas_object_resize(webview, w - 20, h - 20); } static void title_set(Ecore_Evas *ee, const char *title, int progress) { const char *appname = "EFL Test Launcher"; const char *separator = " - "; char label[4096]; int size; if (!title || !strcmp(title, "")) { ecore_evas_title_set(ee, appname); return; } if (progress < 100) size = snprintf(label, sizeof(label), "%s (%d%%)%s%s", title, progress, separator, appname); else size = snprintf(label, sizeof(label), "%s %s%s", title, separator, appname); if (size >= (int)sizeof(label)) return; ecore_evas_title_set(ee, label); } /** * This is en example function to adjust viewport via viewport tag's arguments. * Application can invoke this function in order to adjust viewport tag when it is required. */ static void viewport_set() { ELauncher *app; app = (ELauncher*) eina_list_data_get(windows); ewk_view_fixed_layout_size_set(app->browser, app->viewport.w, app->viewport.h); ewk_view_zoom_set(app->browser, app->viewport.initScale, 0, 0); if (!ewk_view_zoom_range_set(app->browser, app->viewport.minScale, app->viewport.maxScale)) info(" Fail to set zoom range. minScale = %f, maxScale = %f\n", app->viewport.minScale, app->viewport.maxScale); ewk_view_user_scalable_set(app->browser, app->viewport.userScalable); } static void on_title_changed(void *user_data, Evas_Object *webview, void *event_info) { ELauncher *app = (ELauncher *)user_data; const char *title = (const char *)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_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; if (text && *text != '\0') info("%s\n", text); } 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); } /** * "viewport,changed" signal will be always emitted regardless of the viewport existence. * * If you don't want to process the viewport tag, you can either do nothing in this callback * or simply ignore the signal in your application. * * More information about this can be found at http://developer.apple.com/safari/library/docum * entation/appleapplications/reference/safariwebcontent/usingtheviewport/usingtheviewport.html */ static void on_viewport_changed(void* user_data, Evas_Object* webview, void* event_info) { ELauncher *app = (ELauncher *)user_data; float w, h, initScale, minScale, maxScale, devicePixelRatio; Eina_Bool userScalable; ewk_view_viewport_attributes_get(webview, &w, &h, &initScale, &maxScale, &minScale, &devicePixelRatio, &userScalable); /** * If there is no argument in viewport tag, argument's value is -1. */ if ((int)w == -1) w = DEFAULT_WIDTH; if ((int)h == -1) h = DEFAULT_HEIGHT; if ((int)initScale == -1) initScale = DEFAULT_ZOOM_INIT; // There's no scale separated from zooming in webkit-efl. if ((int)minScale == -1) minScale = ewk_view_zoom_range_min_get(webview); if ((int)maxScale == -1) maxScale = ewk_view_zoom_range_max_get(webview); if ((int)devicePixelRatio == -1) devicePixelRatio = ewk_view_device_pixel_ratio_get(webview); if ((int)userScalable == -1) userScalable = EINA_TRUE; app->viewport.w = (int)w; app->viewport.h = (int)h; app->viewport.initScale = initScale; app->viewport.minScale = minScale; app->viewport.maxScale = maxScale; app->viewport.devicePixelRatio = devicePixelRatio; app->viewport.userScalable = userScalable; viewport_set(); } 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 == 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; 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" " flags {\n" " editable=%hhu\n" " selected=%hhu\n" " }\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, 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->flags.editable, ht->flags.selected); 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, "F7")) { info("Zoom out (F7) was pressed.\n"); if (currentZoomLevel > MIN_ZOOM_LEVEL && zoom_level_set(obj, currentZoomLevel - 1)) currentZoomLevel--; } else if (!strcmp(ev->key, "F8")) { info("Zoom in (F8) was pressed.\n"); if (currentZoomLevel < MAX_ZOOM_LEVEL && zoom_level_set(obj, currentZoomLevel + 1)) currentZoomLevel++; } else if (!strcmp(ev->key, "F9")) { info("Create new window (F9) was pressed.\n"); Eina_Rectangle geometry = {0, 0, 0, 0}; browserCreate("http://www.google.com", app->theme, app->userAgent, geometry, app-> backingStore, NULL, app->isFlattening, 0, NULL); } else if (!strcmp(ev->key, "F10")) { 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, "F11")) { info("Pre-render 1 extra column/row with current zoom"); ewk_view_pre_render_relative_radius(obj, 1); } else if (!strcmp(ev->key, "d")) { info("Render suspended"); ewk_view_disable_render(obj); } else if (!strcmp(ev->key, "e")) { info("Render resumed"); ewk_view_enable_render(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_closeWindow(Ecore_Evas *ee) { browserDestroy(ee); } static int quit(Eina_Bool success, const char *msg) { edje_shutdown(); ecore_evas_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, const char *theme, const char *userAgent, Eina_Rectangle geometry, const char *engine, const char *backingStore, unsigned char isFlattening, unsigned char isFullscreen, const char *databasePath) { if ((geometry.w <= 0) && (geometry.h <= 0)) { geometry.w = DEFAULT_WIDTH; geometry.h = DEFAULT_HEIGHT; } ELauncher *app = (ELauncher*) malloc(sizeof(ELauncher)); if (!app) return quit(EINA_FALSE, "ERROR: could not create EWebLauncher window\n"); app->ee = ecore_evas_new(engine, 0, 0, geometry.w, geometry.h, NULL); if (!app->ee) return quit(EINA_FALSE, "ERROR: could not construct evas-ecore\n"); if (isFullscreen) ecore_evas_fullscreen_set(app->ee, EINA_TRUE); ecore_evas_title_set(app->ee, "EFL Test Launcher"); ecore_evas_callback_resize_set(app->ee, on_ecore_evas_resize); ecore_evas_callback_delete_request_set(app->ee, closeWindow); app->evas = ecore_evas_get(app->ee); if (!app->evas) return quit(EINA_FALSE, "ERROR: could not get evas from evas-ecore\n"); app->theme = theme; app->userAgent = userAgent; app->backingStore = backingStore; app->isFlattening = isFlattening; app->bg = evas_object_rectangle_add(app->evas); evas_object_name_set(app->bg, "bg"); evas_object_color_set(app->bg, 255, 0, 255, 255); evas_object_move(app->bg, 0, 0); evas_object_resize(app->bg, geometry.w, geometry.h); evas_object_layer_set(app->bg, EVAS_LAYER_MIN); evas_object_show(app->bg); if (backingStore && !strcasecmp(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_theme_set(app->browser, theme); if (userAgent) ewk_view_setting_user_agent_set(app->browser, userAgent); ewk_view_setting_local_storage_database_path_set(app->browser, databasePath); ewk_view_setting_enable_frame_flattening_set(app->browser, isFlattening); evas_object_name_set(app->browser, "browser"); evas_object_smart_callback_add(app->browser, "title,changed", on_title_changed, app); evas_object_smart_callback_add(app->browser, "load,progress", on_progress, app); evas_object_smart_callback_add(app->browser, "load,finished", on_load_finished, app); evas_object_smart_callback_add(app->browser, "viewport,changed", on_viewport_changed, app); evas_object_smart_callback_add(app->browser, "toolbars,visible,set", on_toolbars_visible_set, app); evas_object_smart_callback_add(app->browser, "toolbars,visible,get", on_toolbars_visible_get, app); evas_object_smart_callback_add(app->browser, "statusbar,visible,set", on_statusbar_visible_set, app); evas_object_smart_callback_add(app->browser, "statusbar,visible,get", on_statusbar_visible_get, app); evas_object_smart_callback_add(app->browser, "scrollbars,visible,set", on_scrollbars_visible_set, app); evas_object_smart_callback_add(app->browser, "scrollbars,visible,get", on_scrollbars_visible_get, app); evas_object_smart_callback_add(app->browser, "menubar,visible,set", on_menubar_visible_set, app); evas_object_smart_callback_add(app->browser, "menubar,visible,get", on_menubar_visible_get, app); evas_object_smart_callback_add(app->browser, "tooltip,text,set", on_tooltip_text_set, app); evas_object_smart_callback_add(app->browser, "inputmethod,changed", on_inputmethod_changed, app); /* ewk_callback_resize_requested_add(app->browser, on_resize_requested, app->ee); */ evas_object_event_callback_add(app->browser, EVAS_CALLBACK_KEY_DOWN, on_key_down, app); evas_object_event_callback_add(app->browser, EVAS_CALLBACK_MOUSE_DOWN, on_mouse_down, app); evas_object_event_callback_add(app->browser, EVAS_CALLBACK_FOCUS_IN, on_focus_in, app); evas_object_event_callback_add(app->browser, EVAS_CALLBACK_FOCUS_OUT, on_focus_out, app); evas_object_event_callback_add(app->browser, EVAS_CALLBACK_DEL, on_browser_del, app); evas_object_move(app->browser, 10, 10); evas_object_resize(app->browser, geometry.w - 20, geometry.h - 20); if (url && (url[0] != '\0')) ewk_view_uri_set(app->browser, url); evas_object_show(app->browser); ecore_evas_show(app->ee); evas_object_focus_set(app->browser, EINA_TRUE); windows = eina_list_append(windows, app); return 1; } static void browserDestroy(Ecore_Evas *ee) { ecore_evas_free(ee); if (!eina_list_count(windows)) ecore_main_loop_quit(); } static void closeWindow(Ecore_Evas *ee) { Eina_List *l; void *app; EINA_LIST_FOREACH(windows, l, app) { if (((ELauncher*) app)->ee == ee) break; } windows = eina_list_remove(windows, app); browserDestroy(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); 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 *defaultTheme = DATA_DIR"/default.edj"; char *rpath; struct stat st; if (!theme) theme = defaultTheme; rpath = realpath(theme, NULL); if (!rpath) return NULL; if (stat(rpath, &st)) { free(rpath); return NULL; } return rpath; } int main(int argc, char *argv[]) { const char *default_url = "http://www.google.com/"; Eina_Rectangle geometry = {0, 0, 0, 0}; char *url = NULL; char *userAgent = NULL; const char *tmp; const char *proxyUri; char path[PATH_MAX]; char *engine = NULL; char *theme = NULL; char *backingStore = (char *)backingStores[1]; unsigned char quitOption = 0; unsigned char isFlattening = 0; unsigned char isFullscreen = 0; int args; Ecore_Getopt_Value values[] = { ECORE_GETOPT_VALUE_STR(engine), ECORE_GETOPT_VALUE_BOOL(quitOption), ECORE_GETOPT_VALUE_STR(backingStore), ECORE_GETOPT_VALUE_BOOL(isFlattening), ECORE_GETOPT_VALUE_BOOL(isFullscreen), ECORE_GETOPT_VALUE_PTR_CAST(geometry), ECORE_GETOPT_VALUE_STR(theme), ECORE_GETOPT_VALUE_STR(userAgent), ECORE_GETOPT_VALUE_INT(verbose), ECORE_GETOPT_VALUE_BOOL(quitOption), ECORE_GETOPT_VALUE_BOOL(quitOption), ECORE_GETOPT_VALUE_BOOL(quitOption), ECORE_GETOPT_VALUE_BOOL(quitOption), ECORE_GETOPT_VALUE_NONE }; if (!ecore_evas_init()) return EXIT_FAILURE; if (!edje_init()) { ecore_evas_shutdown(); return EXIT_FAILURE; } ecore_app_args_set(argc, (const char**) argv); args = ecore_getopt_parse(&options, values, argc, argv); if (args < 0) return quit(EINA_FALSE, "ERROR: could not parse options.\n"); if (quitOption) return quit(EINA_TRUE, NULL); if (args < argc) url = argv[args]; else url = (char*) default_url; themePath = findThemePath(theme); 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()); ecore_file_mkpath(path); ewk_settings_icon_database_path_set(path); ewk_settings_web_database_path_set(path); proxyUri = getenv("http_proxy"); if (proxyUri) ewk_settings_proxy_uri_set(proxyUri); browserCreate(url, themePath, userAgent, geometry, engine, backingStore, isFlattening, isFullscreen, path); ecore_event_handler_add(ECORE_EVENT_SIGNAL_EXIT, main_signal_exit, &windows); ecore_main_loop_begin(); ewk_shutdown(); return quit(EINA_TRUE, NULL); }