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