• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_STORE_DEF_BOOL
125             ('S', "sudo-workaround", "Workaround mode for making Flash work with sudo.", 0),
126         ECORE_GETOPT_COUNT
127             ('v', "verbose", "be more verbose."),
128         ECORE_GETOPT_VERSION
129             ('V', "version"),
130         ECORE_GETOPT_COPYRIGHT
131             ('R', "copyright"),
132         ECORE_GETOPT_LICENSE
133             ('L', "license"),
134         ECORE_GETOPT_HELP
135             ('h', "help"),
136         ECORE_GETOPT_SENTINEL
137     }
138 };
139 
140 typedef struct _Viewport {
141     int w;
142     int h;
143     float initScale;
144     float minScale;
145     float maxScale;
146     float devicePixelRatio;
147     Eina_Bool userScalable;
148 } Viewport;
149 
150 typedef struct _ELauncher {
151     Ecore_Evas *ee;
152     Evas *evas;
153     Evas_Object *bg;
154     Evas_Object *browser;
155     const char *theme;
156     const char *userAgent;
157     const char *backingStore;
158     unsigned char isFlattening;
159     Viewport viewport;
160 } ELauncher;
161 
162 static void browserDestroy(Ecore_Evas *ee);
163 static void closeWindow(Ecore_Evas *ee);
164 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);
165 
166 static void
print_history(Eina_List * list)167 print_history(Eina_List *list)
168 {
169     Eina_List *l;
170     void *d;
171 
172     if (!verbose)
173        return;
174 
175     printf("Session history contains:\n");
176 
177     EINA_LIST_FOREACH(list, l, d) {
178        Ewk_History_Item *item = (Ewk_History_Item*)d;
179        cairo_surface_t *cs = ewk_history_item_icon_surface_get(item);
180        char buf[PATH_MAX];
181        int s = snprintf(buf, sizeof(buf), "/tmp/favicon-%s.png", ewk_history_item_uri_original_get(item));
182        for (s--; s >= (int)sizeof("/tmp/favicon-"); s--) {
183            if (!isalnum(buf[s]) && buf[s] != '.')
184                buf[s] = '_';
185        }
186        cs = ewk_history_item_icon_surface_get(item);
187 
188        if (cs && cairo_surface_status(cs) == CAIRO_STATUS_SUCCESS)
189            cairo_surface_write_to_png(cs, buf);
190        else
191            buf[0] = '\0';
192 
193        printf("* '%s' title='%s' icon='%s'\n",
194               ewk_history_item_uri_original_get(item),
195               ewk_history_item_title_get(item), buf);
196     }
197 }
198 
199 static int
nearest_zoom_level_get(float factor)200 nearest_zoom_level_get(float factor)
201 {
202     int i, intFactor = (int)(factor * 100.0);
203     for (i = 0; zoomLevels[i] <= intFactor; i++) { }
204     printf("factor=%f, intFactor=%d, zoomLevels[%d]=%d, zoomLevels[%d]=%d\n",
205            factor, intFactor, i-1, zoomLevels[i-1], i, zoomLevels[i]);
206     if (intFactor - zoomLevels[i-1] < zoomLevels[i] - intFactor)
207         return i - 1;
208     return i;
209 }
210 
211 static Eina_Bool
zoom_level_set(Evas_Object * webview,int level)212 zoom_level_set(Evas_Object *webview, int level)
213 {
214     float factor = ((float) zoomLevels[level]) / 100.0;
215     Evas_Coord ox, oy, mx, my, cx, cy;
216     evas_pointer_canvas_xy_get(evas_object_evas_get(webview), &mx, &my);
217     evas_object_geometry_get(webview, &ox, &oy, NULL, NULL);
218     cx = mx - ox;
219     cy = my - oy;
220     return ewk_view_zoom_animated_set(webview, factor, 0.5, cx, cy);
221 }
222 
223 static void
on_ecore_evas_resize(Ecore_Evas * ee)224 on_ecore_evas_resize(Ecore_Evas *ee)
225 {
226     Evas_Object *webview;
227     Evas_Object *bg;
228     int w, h;
229 
230     ecore_evas_geometry_get(ee, NULL, NULL, &w, &h);
231 
232     bg = evas_object_name_find(ecore_evas_get(ee), "bg");
233     evas_object_move(bg, 0, 0);
234     evas_object_resize(bg, w, h);
235 
236     webview = evas_object_name_find(ecore_evas_get(ee), "browser");
237     evas_object_move(webview, 10, 10);
238     evas_object_resize(webview, w - 20, h - 20);
239 }
240 
241 static void
title_set(Ecore_Evas * ee,const char * title,int progress)242 title_set(Ecore_Evas *ee, const char *title, int progress)
243 {
244     const char *appname = "EFL Test Launcher";
245     const char *separator = " - ";
246     char label[4096];
247     int size;
248 
249     if (!title || !strcmp(title, "")) {
250         ecore_evas_title_set(ee, appname);
251         return;
252     }
253 
254     if (progress < 100)
255         size = snprintf(label, sizeof(label), "%s (%d%%)%s%s", title, progress, separator, appname);
256     else
257         size = snprintf(label, sizeof(label), "%s %s%s", title, separator, appname);
258 
259     if (size >= (int)sizeof(label))
260         return;
261 
262     ecore_evas_title_set(ee, label);
263 }
264 
265 /**
266  * This is en example function to adjust viewport via viewport tag's arguments.
267  * Application can invoke this function in order to adjust viewport tag when it is required.
268  */
269 static void
viewport_set()270 viewport_set()
271 {
272     ELauncher *app;
273     app = (ELauncher*) eina_list_data_get(windows);
274 
275     ewk_view_fixed_layout_size_set(app->browser, app->viewport.w, app->viewport.h);
276     ewk_view_zoom_set(app->browser, app->viewport.initScale, 0, 0);
277     if (!ewk_view_zoom_range_set(app->browser, app->viewport.minScale, app->viewport.maxScale))
278         info(" Fail to set zoom range. minScale = %f, maxScale = %f\n", app->viewport.minScale, app->viewport.maxScale);
279     ewk_view_user_scalable_set(app->browser, app->viewport.userScalable);
280 }
281 
282 static void
on_title_changed(void * user_data,Evas_Object * webview,void * event_info)283 on_title_changed(void *user_data, Evas_Object *webview, void *event_info)
284 {
285     ELauncher *app = (ELauncher *)user_data;
286     const char *title = (const char *)event_info;
287 
288     title_set(app->ee, title, 100);
289 }
290 
291 static void
on_progress(void * user_data,Evas_Object * webview,void * event_info)292 on_progress(void *user_data, Evas_Object *webview, void *event_info)
293 {
294     ELauncher *app = (ELauncher *)user_data;
295     double *progress = (double *)event_info;
296 
297     title_set(app->ee, ewk_view_title_get(app->browser), *progress * 100);
298 }
299 
300 static void
on_load_finished(void * user_data,Evas_Object * webview,void * event_info)301 on_load_finished(void *user_data, Evas_Object *webview, void *event_info)
302 {
303     const Ewk_Frame_Load_Error *err = (const Ewk_Frame_Load_Error *)event_info;
304 
305     if (!err)
306         info("Succeeded loading page.\n");
307     else if (err->is_cancellation)
308         info("Load was cancelled.\n");
309     else
310         info("Failed loading page: %d %s \"%s\", url=%s\n",
311              err->code, err->domain, err->description, err->failing_url);
312 
313     currentZoom = ewk_view_zoom_get(webview);
314     currentZoomLevel = nearest_zoom_level_get(currentZoom);
315     info("WebCore Zoom=%f, currentZoomLevel=%d\n", currentZoom, currentZoomLevel);
316 }
317 
318 static void
on_toolbars_visible_set(void * user_data,Evas_Object * webview,void * event_info)319 on_toolbars_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("Toolbars visible changed: show");
324         windowProperties.toolbarsVisible = EINA_TRUE;
325     } else {
326         info("Toolbars visible changed: hide");
327         windowProperties.toolbarsVisible = EINA_FALSE;
328     }
329 }
330 
331 static void
on_toolbars_visible_get(void * user_data,Evas_Object * webview,void * event_info)332 on_toolbars_visible_get(void* user_data, Evas_Object* webview, void* event_info)
333 {
334     Eina_Bool *visible = (Eina_Bool *)event_info;
335     *visible = windowProperties.toolbarsVisible;
336 }
337 
338 static void
on_statusbar_visible_set(void * user_data,Evas_Object * webview,void * event_info)339 on_statusbar_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("Statusbar visible changed: show");
344         windowProperties.statusbarVisible = EINA_TRUE;
345     } else {
346         info("Statusbar visible changed: hide");
347         windowProperties.statusbarVisible = EINA_FALSE;
348     }
349 }
350 
351 static void
on_statusbar_visible_get(void * user_data,Evas_Object * webview,void * event_info)352 on_statusbar_visible_get(void* user_data, Evas_Object* webview, void* event_info)
353 {
354     Eina_Bool *visible = (Eina_Bool *)event_info;
355     *visible = windowProperties.statusbarVisible;
356 }
357 
358 static void
on_scrollbars_visible_set(void * user_data,Evas_Object * webview,void * event_info)359 on_scrollbars_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("Scrollbars visible changed: show");
364         windowProperties.scrollbarsVisible = EINA_TRUE;
365     } else {
366         info("Scrollbars visible changed: hide");
367         windowProperties.scrollbarsVisible = EINA_FALSE;
368     }
369 }
370 
371 static void
on_scrollbars_visible_get(void * user_data,Evas_Object * webview,void * event_info)372 on_scrollbars_visible_get(void* user_data, Evas_Object* webview, void* event_info)
373 {
374     Eina_Bool *visible = (Eina_Bool *)event_info;
375     *visible = windowProperties.scrollbarsVisible;
376 }
377 
378 static void
on_menubar_visible_set(void * user_data,Evas_Object * webview,void * event_info)379 on_menubar_visible_set(void* user_data, Evas_Object* webview, void* event_info)
380 {
381     Eina_Bool *visible = (Eina_Bool *)event_info;
382     if (*visible) {
383         info("Menubar visible changed: show");
384         windowProperties.menubarVisible = EINA_TRUE;
385     } else {
386         info("Menubar visible changed: hide");
387         windowProperties.menubarVisible = EINA_FALSE;
388     }
389 }
390 
391 static void
on_menubar_visible_get(void * user_data,Evas_Object * webview,void * event_info)392 on_menubar_visible_get(void* user_data, Evas_Object* webview, void* event_info)
393 {
394     Eina_Bool *visible = (Eina_Bool *)event_info;
395     *visible = windowProperties.menubarVisible;
396 }
397 
398 static void
on_tooltip_text_set(void * user_data,Evas_Object * webview,void * event_info)399 on_tooltip_text_set(void* user_data, Evas_Object* webview, void* event_info)
400 {
401     const char *text = (const char *)event_info;
402     if (text && *text != '\0')
403         info("%s\n", text);
404 }
405 
406 static void
on_inputmethod_changed(void * user_data,Evas_Object * webview,void * event_info)407 on_inputmethod_changed(void* user_data, Evas_Object* webview, void* event_info)
408 {
409     Eina_Bool active = (Eina_Bool)(long)event_info;
410     unsigned int imh;
411     info("Keyboard changed: %d\n", active);
412 
413     if (!active)
414         return;
415 
416     imh = ewk_view_imh_get(webview);
417     info("    Keyboard flags: %#.2x\n", imh);
418 
419 }
420 
421 /**
422  * "viewport,changed" signal will be always emitted regardless of the viewport existence.
423  *
424  * If you don't want to process the viewport tag, you can either do nothing in this callback
425  * or simply ignore the signal in your application.
426  *
427  * More information about this can be found at http://developer.apple.com/safari/library/docum
428  * entation/appleapplications/reference/safariwebcontent/usingtheviewport/usingtheviewport.html
429  */
430 static void
on_viewport_changed(void * user_data,Evas_Object * webview,void * event_info)431 on_viewport_changed(void* user_data, Evas_Object* webview, void* event_info)
432 {
433     ELauncher *app = (ELauncher *)user_data;
434 
435     float w, h, initScale, minScale, maxScale, devicePixelRatio;
436     Eina_Bool userScalable;
437 
438     ewk_view_viewport_attributes_get(webview, &w, &h, &initScale, &maxScale, &minScale, &devicePixelRatio, &userScalable);
439 
440     /**
441      * If there is no argument in viewport tag, argument's value is -1.
442      */
443     if ((int)w == -1)
444         w = DEFAULT_WIDTH;
445     if ((int)h == -1)
446         h = DEFAULT_HEIGHT;
447     if ((int)initScale == -1)
448         initScale = DEFAULT_ZOOM_INIT; // There's no scale separated from zooming in webkit-efl.
449     if ((int)minScale == -1)
450         minScale = ewk_view_zoom_range_min_get(webview);
451     if ((int)maxScale == -1)
452         maxScale = ewk_view_zoom_range_max_get(webview);
453     if ((int)devicePixelRatio == -1)
454         devicePixelRatio = ewk_view_device_pixel_ratio_get(webview);
455     if ((int)userScalable == -1)
456         userScalable = EINA_TRUE;
457 
458     app->viewport.w = (int)w;
459     app->viewport.h = (int)h;
460     app->viewport.initScale = initScale;
461     app->viewport.minScale = minScale;
462     app->viewport.maxScale = maxScale;
463     app->viewport.devicePixelRatio = devicePixelRatio;
464     app->viewport.userScalable = userScalable;
465     viewport_set();
466 }
467 
468 static void
on_mouse_down(void * data,Evas * e,Evas_Object * webview,void * event_info)469 on_mouse_down(void* data, Evas* e, Evas_Object* webview, void* event_info)
470 {
471     Evas_Event_Mouse_Down *ev = (Evas_Event_Mouse_Down*) event_info;
472     if (ev->button == 2)
473         evas_object_focus_set(webview, !evas_object_focus_get(webview));
474 }
475 
476 static void
on_focus_out(void * data,Evas * e,Evas_Object * obj,void * event_info)477 on_focus_out(void *data, Evas *e, Evas_Object *obj, void *event_info)
478 {
479     info("the webview lost keyboard focus\n");
480 }
481 
482 static void
on_focus_in(void * data,Evas * e,Evas_Object * obj,void * event_info)483 on_focus_in(void *data, Evas *e, Evas_Object *obj, void *event_info)
484 {
485     info("the webview gained keyboard focus\n");
486 }
487 
488 static void
on_key_down(void * data,Evas * e,Evas_Object * obj,void * event_info)489 on_key_down(void *data, Evas *e, Evas_Object *obj, void *event_info)
490 {
491     Evas_Event_Key_Down *ev = (Evas_Event_Key_Down*) event_info;
492     ELauncher *app = data;
493     static const char *encodings[] = {
494         "ISO-8859-1",
495         "UTF-8",
496         NULL
497     };
498     static int currentEncoding = -1;
499 
500     if (!strcmp(ev->key, "Escape")) {
501         closeWindow(app->ee);
502     } else if (!strcmp(ev->key, "F1")) {
503         info("Back (F1) was pressed\n");
504         if (ewk_view_back_possible(obj)) {
505             Ewk_History *history = ewk_view_history_get(obj);
506             Eina_List *list = ewk_history_back_list_get(history);
507             print_history(list);
508             ewk_history_item_list_free(list);
509             ewk_view_back(obj);
510         } else
511             info("Back ignored: No back history\n");
512     } else if (!strcmp(ev->key, "F2")) {
513         info("Forward (F2) was pressed\n");
514         if (ewk_view_forward_possible(obj)) {
515             Ewk_History *history = ewk_view_history_get(obj);
516             Eina_List *list = ewk_history_forward_list_get(history);
517             print_history(list);
518             ewk_history_item_list_free(list);
519             ewk_view_forward(obj);
520         } else
521             info("Forward ignored: No forward history\n");
522     } else if (!strcmp(ev->key, "F3")) {
523         currentEncoding++;
524         currentEncoding %= (sizeof(encodings) / sizeof(encodings[0]));
525         info("Set encoding (F3) pressed. New encoding to %s", encodings[currentEncoding]);
526         ewk_view_setting_encoding_custom_set(obj, encodings[currentEncoding]);
527     } else if (!strcmp(ev->key, "F4")) {
528         Evas_Object *frame = ewk_view_frame_main_get(obj);
529         Evas_Coord x, y;
530         Ewk_Hit_Test *ht;
531 
532         evas_pointer_canvas_xy_get(evas_object_evas_get(obj), &x, &y);
533         ht = ewk_frame_hit_test_new(frame, x, y);
534         if (!ht)
535             printf("No hit test returned for point %d,%d\n", x, y);
536         else {
537             printf("Hit test for point %d,%d\n"
538                    "  pos=%3d,%3d\n"
539                    "  bounding_box=%d,%d + %dx%d\n"
540                    "  title='%s'\n"
541                    "  alternate_text='%s'\n"
542                    "  frame=%p (%s)\n"
543                    "  link {\n"
544                    "    text='%s'\n"
545                    "    url='%s'\n"
546                    "    title='%s'\n"
547                    "    target frame=%p (%s)\n"
548                    "  }\n"
549                    "  flags {\n"
550                    "    editable=%hhu\n"
551                    "    selected=%hhu\n"
552                    "  }\n",
553                    x, y,
554                    ht->x, ht->y,
555                    ht->bounding_box.x, ht->bounding_box.y, ht->bounding_box.w, ht->bounding_box.h,
556                    ht->title,
557                    ht->alternate_text,
558                    ht->frame, evas_object_name_get(ht->frame),
559                    ht->link.text,
560                    ht->link.url,
561                    ht->link.title,
562                    ht->link.target_frame, evas_object_name_get(ht->link.target_frame),
563                    ht->flags.editable,
564                    ht->flags.selected);
565             ewk_frame_hit_test_free(ht);
566         }
567 
568     } else if (!strcmp(ev->key, "F5")) {
569         info("Reload (F5) was pressed, reloading.\n");
570         ewk_view_reload(obj);
571     } else if (!strcmp(ev->key, "F6")) {
572         info("Stop (F6) was pressed, stop loading.\n");
573         ewk_view_stop(obj);
574     } else if (!strcmp(ev->key, "F12")) {
575         Eina_Bool status = ewk_view_setting_spatial_navigation_get(obj);
576         ewk_view_setting_spatial_navigation_set(obj, !status);
577         info("Command::keyboard navigation toggle\n");
578     } else if (!strcmp(ev->key, "F7")) {
579         info("Zoom out (F7) was pressed.\n");
580         if (currentZoomLevel > MIN_ZOOM_LEVEL && zoom_level_set(obj, currentZoomLevel - 1))
581             currentZoomLevel--;
582     } else if (!strcmp(ev->key, "F8")) {
583         info("Zoom in (F8) was pressed.\n");
584         if (currentZoomLevel < MAX_ZOOM_LEVEL && zoom_level_set(obj, currentZoomLevel + 1))
585             currentZoomLevel++;
586     } else if (!strcmp(ev->key, "F9")) {
587         info("Create new window (F9) was pressed.\n");
588         Eina_Rectangle geometry = {0, 0, 0, 0};
589         browserCreate("http://www.google.com",
590                        app->theme, app->userAgent, geometry, app-> backingStore,
591                        NULL, app->isFlattening, 0, NULL);
592     } else if (!strcmp(ev->key, "F10")) {
593         Evas_Coord x, y, w, h;
594         Evas_Object *frame = ewk_view_frame_main_get(obj);
595         float zoom = zoomLevels[currentZoomLevel] / 100.0;
596 
597         ewk_frame_visible_content_geometry_get(frame, EINA_FALSE, &x, &y, &w, &h);
598         x -= w;
599         y -= h;
600         w *= 4;
601         h *= 4;
602         info("Pre-render %d,%d + %dx%d\n", x, y, w, h);
603         ewk_view_pre_render_region(obj, x, y, w, h, zoom);
604     } else if (!strcmp(ev->key, "F11")) {
605         info("Pre-render 1 extra column/row with current zoom");
606         ewk_view_pre_render_relative_radius(obj, 1);
607     } else if (!strcmp(ev->key, "d")) {
608         info("Render suspended");
609         ewk_view_disable_render(obj);
610     } else if (!strcmp(ev->key, "e")) {
611         info("Render resumed");
612         ewk_view_enable_render(obj);
613     }
614 }
615 
616 static void
on_browser_del(void * data,Evas * evas,Evas_Object * browser,void * event)617 on_browser_del(void *data, Evas *evas, Evas_Object *browser, void *event)
618 {
619     ELauncher *app = (ELauncher*) data;
620 
621     evas_object_event_callback_del(app->browser, EVAS_CALLBACK_KEY_DOWN, on_key_down);
622     evas_object_event_callback_del(app->browser, EVAS_CALLBACK_MOUSE_DOWN, on_mouse_down);
623     evas_object_event_callback_del(app->browser, EVAS_CALLBACK_FOCUS_IN, on_focus_in);
624     evas_object_event_callback_del(app->browser, EVAS_CALLBACK_FOCUS_OUT, on_focus_out);
625     evas_object_event_callback_del(app->browser, EVAS_CALLBACK_DEL, on_browser_del);
626 }
627 
628 static void
on_closeWindow(Ecore_Evas * ee)629 on_closeWindow(Ecore_Evas *ee)
630 {
631     browserDestroy(ee);
632 }
633 
634 static int
quit(Eina_Bool success,const char * msg)635 quit(Eina_Bool success, const char *msg)
636 {
637     edje_shutdown();
638     ecore_evas_shutdown();
639 
640     if (msg)
641         fputs(msg, (success) ? stdout : stderr);
642 
643     if (themePath) {
644         free(themePath);
645         themePath = NULL;
646     }
647 
648     if (!success)
649         return EXIT_FAILURE;
650 
651     return EXIT_SUCCESS;
652 }
653 
654 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)655 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)
656 {
657     if ((geometry.w <= 0) && (geometry.h <= 0)) {
658         geometry.w = DEFAULT_WIDTH;
659         geometry.h = DEFAULT_HEIGHT;
660     }
661 
662     ELauncher *app = (ELauncher*) malloc(sizeof(ELauncher));
663     if (!app)
664         return quit(EINA_FALSE, "ERROR: could not create EWebLauncher window\n");
665 
666     app->ee = ecore_evas_new(engine, 0, 0, geometry.w, geometry.h, NULL);
667 
668     if (!app->ee)
669         return quit(EINA_FALSE, "ERROR: could not construct evas-ecore\n");
670 
671     if (isFullscreen)
672         ecore_evas_fullscreen_set(app->ee, EINA_TRUE);
673 
674     ecore_evas_title_set(app->ee, "EFL Test Launcher");
675     ecore_evas_callback_resize_set(app->ee, on_ecore_evas_resize);
676     ecore_evas_callback_delete_request_set(app->ee, closeWindow);
677 
678     app->evas = ecore_evas_get(app->ee);
679 
680     if (!app->evas)
681         return quit(EINA_FALSE, "ERROR: could not get evas from evas-ecore\n");
682 
683     app->theme = theme;
684     app->userAgent = userAgent;
685     app->backingStore = backingStore;
686     app->isFlattening = isFlattening;
687 
688     app->bg = evas_object_rectangle_add(app->evas);
689     evas_object_name_set(app->bg, "bg");
690     evas_object_color_set(app->bg, 255, 0, 255, 255);
691     evas_object_move(app->bg, 0, 0);
692     evas_object_resize(app->bg, geometry.w, geometry.h);
693     evas_object_layer_set(app->bg, EVAS_LAYER_MIN);
694     evas_object_show(app->bg);
695 
696     if (backingStore && !strcasecmp(backingStore, "tiled")) {
697         app->browser = ewk_view_tiled_add(app->evas);
698         info("backing store: tiled\n");
699     } else {
700         app->browser = ewk_view_single_add(app->evas);
701         info("backing store: single\n");
702     }
703 
704     ewk_view_theme_set(app->browser, theme);
705     if (userAgent)
706         ewk_view_setting_user_agent_set(app->browser, userAgent);
707     ewk_view_setting_local_storage_database_path_set(app->browser, databasePath);
708     ewk_view_setting_enable_frame_flattening_set(app->browser, isFlattening);
709 
710     evas_object_name_set(app->browser, "browser");
711 
712     evas_object_smart_callback_add(app->browser, "title,changed", on_title_changed, app);
713     evas_object_smart_callback_add(app->browser, "load,progress", on_progress, app);
714     evas_object_smart_callback_add(app->browser, "load,finished", on_load_finished, app);
715     evas_object_smart_callback_add(app->browser, "viewport,changed", on_viewport_changed, app);
716 
717     evas_object_smart_callback_add(app->browser, "toolbars,visible,set", on_toolbars_visible_set, app);
718     evas_object_smart_callback_add(app->browser, "toolbars,visible,get", on_toolbars_visible_get, app);
719     evas_object_smart_callback_add(app->browser, "statusbar,visible,set", on_statusbar_visible_set, app);
720     evas_object_smart_callback_add(app->browser, "statusbar,visible,get", on_statusbar_visible_get, app);
721     evas_object_smart_callback_add(app->browser, "scrollbars,visible,set", on_scrollbars_visible_set, app);
722     evas_object_smart_callback_add(app->browser, "scrollbars,visible,get", on_scrollbars_visible_get, app);
723     evas_object_smart_callback_add(app->browser, "menubar,visible,set", on_menubar_visible_set, app);
724     evas_object_smart_callback_add(app->browser, "menubar,visible,get", on_menubar_visible_get, app);
725     evas_object_smart_callback_add(app->browser, "tooltip,text,set", on_tooltip_text_set, app);
726     evas_object_smart_callback_add(app->browser, "inputmethod,changed", on_inputmethod_changed, app);
727 
728 /*     ewk_callback_resize_requested_add(app->browser, on_resize_requested, app->ee); */
729 
730     evas_object_event_callback_add(app->browser, EVAS_CALLBACK_KEY_DOWN, on_key_down, app);
731     evas_object_event_callback_add(app->browser, EVAS_CALLBACK_MOUSE_DOWN, on_mouse_down, app);
732     evas_object_event_callback_add(app->browser, EVAS_CALLBACK_FOCUS_IN, on_focus_in, app);
733     evas_object_event_callback_add(app->browser, EVAS_CALLBACK_FOCUS_OUT, on_focus_out, app);
734     evas_object_event_callback_add(app->browser, EVAS_CALLBACK_DEL, on_browser_del, app);
735 
736     evas_object_move(app->browser, 10, 10);
737     evas_object_resize(app->browser, geometry.w - 20, geometry.h - 20);
738 
739     if (url && (url[0] != '\0'))
740         ewk_view_uri_set(app->browser, url);
741 
742     evas_object_show(app->browser);
743     ecore_evas_show(app->ee);
744 
745     evas_object_focus_set(app->browser, EINA_TRUE);
746 
747     windows = eina_list_append(windows, app);
748 
749     return 1;
750 }
751 
752 static void
browserDestroy(Ecore_Evas * ee)753 browserDestroy(Ecore_Evas *ee)
754 {
755     ecore_evas_free(ee);
756     if (!eina_list_count(windows))
757         ecore_main_loop_quit();
758 }
759 
760 static void
closeWindow(Ecore_Evas * ee)761 closeWindow(Ecore_Evas *ee)
762 {
763     Eina_List *l;
764     void *app;
765     EINA_LIST_FOREACH(windows, l, app)
766     {
767         if (((ELauncher*) app)->ee == ee)
768             break;
769     }
770     windows = eina_list_remove(windows, app);
771     browserDestroy(ee);
772     free(app);
773 }
774 
775 static Eina_Bool
main_signal_exit(void * data,int ev_type,void * ev)776 main_signal_exit(void *data, int ev_type, void *ev)
777 {
778     ELauncher *app;
779     while (windows) {
780         app = (ELauncher*) eina_list_data_get(windows);
781         ecore_evas_free(app->ee);
782         windows = eina_list_remove(windows, app);
783     }
784     if (!eina_list_count(windows))
785         ecore_main_loop_quit();
786     return EINA_TRUE;
787 }
788 
789 static char *
findThemePath(const char * theme)790 findThemePath(const char *theme)
791 {
792     const char *defaultTheme = DATA_DIR"/default.edj";
793     char *rpath;
794     struct stat st;
795 
796     if (!theme)
797         theme = defaultTheme;
798 
799     rpath = realpath(theme, NULL);
800     if (!rpath)
801         return NULL;
802 
803     if (stat(rpath, &st)) {
804         free(rpath);
805         return NULL;
806     }
807 
808     return rpath;
809 }
810 
811 int
main(int argc,char * argv[])812 main(int argc, char *argv[])
813 {
814     const char *default_url = "http://www.google.com/";
815 
816     Eina_Rectangle geometry = {0, 0, 0, 0};
817     char *url = NULL;
818     char *userAgent = NULL;
819     const char *tmp;
820     const char *proxyUri;
821     char path[PATH_MAX];
822 
823     char *engine = NULL;
824     char *theme = NULL;
825     char *backingStore = (char *)backingStores[1];
826 
827     unsigned char quitOption = 0;
828     unsigned char isFlattening = 0;
829     unsigned char isFullscreen = 0;
830     int args;
831 
832     Ecore_Getopt_Value values[] = {
833         ECORE_GETOPT_VALUE_STR(engine),
834         ECORE_GETOPT_VALUE_BOOL(quitOption),
835         ECORE_GETOPT_VALUE_STR(backingStore),
836         ECORE_GETOPT_VALUE_BOOL(isFlattening),
837         ECORE_GETOPT_VALUE_BOOL(isFullscreen),
838         ECORE_GETOPT_VALUE_PTR_CAST(geometry),
839         ECORE_GETOPT_VALUE_STR(theme),
840         ECORE_GETOPT_VALUE_STR(userAgent),
841         ECORE_GETOPT_VALUE_INT(verbose),
842         ECORE_GETOPT_VALUE_BOOL(quitOption),
843         ECORE_GETOPT_VALUE_BOOL(quitOption),
844         ECORE_GETOPT_VALUE_BOOL(quitOption),
845         ECORE_GETOPT_VALUE_BOOL(quitOption),
846         ECORE_GETOPT_VALUE_NONE
847     };
848 
849     if (!ecore_evas_init())
850         return EXIT_FAILURE;
851 
852     if (!edje_init()) {
853         ecore_evas_shutdown();
854         return EXIT_FAILURE;
855     }
856 
857     ecore_app_args_set(argc, (const char**) argv);
858     args = ecore_getopt_parse(&options, values, argc, argv);
859 
860     if (args < 0)
861        return quit(EINA_FALSE, "ERROR: could not parse options.\n");
862 
863     if (quitOption)
864         return quit(EINA_TRUE, NULL);
865 
866     if (args < argc)
867         url = argv[args];
868     else
869         url = (char*) default_url;
870 
871     themePath = findThemePath(theme);
872     if (!themePath)
873         return quit(EINA_FALSE, "ERROR: could not find theme.\n");
874 
875     ewk_init();
876     tmp = getenv("TMPDIR");
877     if (!tmp)
878         tmp = "/tmp";
879     snprintf(path, sizeof(path), "%s/.ewebkit-%u", tmp, getuid());
880     ecore_file_mkpath(path);
881     ewk_settings_icon_database_path_set(path);
882     ewk_settings_web_database_path_set(path);
883 
884     proxyUri = getenv("http_proxy");
885     if (proxyUri)
886         ewk_settings_proxy_uri_set(proxyUri);
887 
888     browserCreate(url, themePath, userAgent, geometry, engine, backingStore, isFlattening, isFullscreen, path);
889     ecore_event_handler_add(ECORE_EVENT_SIGNAL_EXIT, main_signal_exit, &windows);
890 
891     ecore_main_loop_begin();
892 
893     ewk_shutdown();
894 
895     return quit(EINA_TRUE, NULL);
896 }
897