main.c 72 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888
  1. /*
  2. * Copyright (C) 2012 Samsung Electronics
  3. * Copyright (C) 2012 Intel Corporation. All rights reserved.
  4. *
  5. * This library is free software; you can redistribute it and/or
  6. * modify it under the terms of the GNU Lesser General Public
  7. * License as published by the Free Software Foundation; either
  8. * version 2 of the License, or (at your option) any later version.
  9. *
  10. * This library is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  13. * Lesser General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU Lesser General Public
  16. * License along with this library; if not, write to the Free Software
  17. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  18. */
  19. #include "EWebKit2.h"
  20. #include "url_utils.h"
  21. #include <Ecore.h>
  22. #include <Ecore_Evas.h>
  23. #include <Ecore_Getopt.h>
  24. #include <Eina.h>
  25. #include <Elementary.h>
  26. #include <Evas.h>
  27. static const char DEFAULT_URL[] = "http://www.google.com/";
  28. static const char APP_NAME[] = "EFL MiniBrowser";
  29. static const int TOOL_BAR_ICON_SIZE = 24;
  30. static const int TOOL_BAR_BUTTON_SIZE = 32;
  31. static const int SEARCH_FIELD_SIZE = 200;
  32. static const int SEARCH_BUTTON_SIZE = 25;
  33. static const int MAX_SEARCH_COUNT = 100;
  34. static const int DEFAULT_SEARCH_FLAGS = EWK_FIND_OPTIONS_SHOW_HIGHLIGHT | EWK_FIND_OPTIONS_CASE_INSENSITIVE | EWK_FIND_OPTIONS_WRAP_AROUND;
  35. static const double TOOLTIP_DELAY_SECONDS = 1.0;
  36. #define info(format, args...) \
  37. do { \
  38. if (verbose) \
  39. printf(format"\n", ##args); \
  40. } while (0)
  41. static int verbose = 1;
  42. static Eina_List *windows = NULL;
  43. static char *evas_engine_name = NULL;
  44. static char *user_agent_string = NULL;
  45. static Eina_Bool encoding_detector_enabled = EINA_FALSE;
  46. static Eina_Bool frame_flattening_enabled = EINA_FALSE;
  47. static Eina_Bool local_storage_enabled = EINA_TRUE;
  48. static Eina_Bool fullscreen_enabled = EINA_FALSE;
  49. static Eina_Bool spell_checking_enabled = EINA_FALSE;
  50. static int window_width = 800;
  51. static int window_height = 600;
  52. /* Default value of device_pixel_ratio is '0' so that we don't set custom device
  53. * scale factor unless it's required by the User. */
  54. static double device_pixel_ratio = 0;
  55. static Eina_Bool legacy_behavior_enabled = EINA_FALSE;
  56. #define DEFAULT_ZOOM_LEVEL 5 // Set default zoom level to 1.0 (index 5 on zoomLevels).
  57. // The zoom values are chosen to be like in Mozilla Firefox 3.
  58. const static float zoomLevels[] = {0.3, 0.5, 0.67, 0.8, 0.9, 1.0, 1.1, 1.2, 1.33, 1.5, 1.7, 2.0, 2.4, 3.0};
  59. static Eina_Bool
  60. zoom_level_set(Evas_Object *webview, int level)
  61. {
  62. if (level < 0 || level >= sizeof(zoomLevels) / sizeof(float))
  63. return EINA_FALSE;
  64. Evas_Coord ox, oy, mx, my, cx, cy;
  65. evas_pointer_canvas_xy_get(evas_object_evas_get(webview), &mx, &my); // Get current mouse position on window.
  66. evas_object_geometry_get(webview, &ox, &oy, NULL, NULL); // Get webview's position on window.
  67. cx = mx - ox; // current x position = mouse x position - webview x position
  68. cy = my - oy; // current y position = mouse y position - webview y position
  69. Eina_Bool result = ewk_view_scale_set(webview, zoomLevels[level], cx, cy);
  70. return result;
  71. }
  72. static Ewk_View_Smart_Class *miniBrowserViewSmartClass()
  73. {
  74. static Ewk_View_Smart_Class ewkViewClass = EWK_VIEW_SMART_CLASS_INIT_NAME_VERSION("MiniBrowser_View");
  75. return &ewkViewClass;
  76. }
  77. typedef struct _Tooltip_Information {
  78. Ecore_Timer *show_timer;
  79. Eina_Bool activated;
  80. Eina_Bool text_set;
  81. Eina_Bool shown;
  82. } Tooltip_Information;
  83. typedef struct _Color_Selector {
  84. Ewk_Color_Picker *ewk_picker;
  85. Evas_Object *elm_selector;
  86. Evas_Object *elm_selector_window;
  87. } Color_Selector;
  88. typedef struct _Browser_Window {
  89. Evas_Object *elm_window;
  90. Evas_Object *ewk_view;
  91. Evas_Object *url_bar;
  92. Evas_Object *back_button;
  93. Evas_Object *forward_button;
  94. struct {
  95. Evas_Object *elm_menu;
  96. Ewk_Popup_Menu *ewk_menu;
  97. } popup;
  98. struct {
  99. Evas_Object *search_bar;
  100. Evas_Object *search_field;
  101. Evas_Object *backward_button;
  102. Evas_Object *forward_button;
  103. } search;
  104. int current_zoom_level;
  105. Tooltip_Information tooltip;
  106. Color_Selector color_selector;
  107. struct {
  108. Evas_Object *elm_menu;
  109. Ewk_Context_Menu *ewk_menu;
  110. } context_menu;
  111. } Browser_Window;
  112. typedef struct _File_Selector_Data {
  113. Browser_Window* parent;
  114. Evas_Object *elm_window;
  115. Ewk_File_Chooser_Request *request;
  116. } File_Selector_Data;
  117. typedef struct _Auth_Data {
  118. Evas_Object *popup;
  119. Ewk_Auth_Request *request;
  120. Evas_Object *username_entry;
  121. Evas_Object *password_entry;
  122. } Auth_Data;
  123. static const Ecore_Getopt options = {
  124. "MiniBrowser",
  125. "%prog [options] [url]",
  126. "0.0.1",
  127. "(C)2012 Samsung Electronics\n (C)2012 Intel Corporation\n",
  128. "",
  129. "Test Web Browser using the Enlightenment Foundation Libraries (EFL) port of WebKit2",
  130. EINA_TRUE, {
  131. ECORE_GETOPT_STORE_STR
  132. ('e', "engine", "ecore-evas engine to use."),
  133. ECORE_GETOPT_STORE_STR
  134. ('s', "window-size", "window size in following format (width)x(height)."),
  135. ECORE_GETOPT_STORE_STR
  136. ('u', "user-agent", "user agent to set."),
  137. ECORE_GETOPT_STORE_DEF_BOOL
  138. ('b', "legacy", "Legacy mode", EINA_FALSE),
  139. ECORE_GETOPT_STORE_DOUBLE
  140. ('r', "device-pixel-ratio", "Ratio between the CSS units and device pixels."),
  141. ECORE_GETOPT_CALLBACK_NOARGS
  142. ('E', "list-engines", "list ecore-evas engines.",
  143. ecore_getopt_callback_ecore_evas_list_engines, NULL),
  144. ECORE_GETOPT_STORE_DEF_BOOL
  145. ('c', "encoding-detector", "enable/disable encoding detector", EINA_FALSE),
  146. ECORE_GETOPT_STORE_DEF_BOOL
  147. ('f', "flattening", "frame flattening.", EINA_FALSE),
  148. ECORE_GETOPT_STORE_DEF_BOOL
  149. ('l', "local-storage", "HTML5 local storage support (enabled by default).", EINA_TRUE),
  150. ECORE_GETOPT_STORE_DEF_BOOL
  151. ('F', "full-screen", "start in full-screen.", EINA_FALSE),
  152. ECORE_GETOPT_STORE_DEF_BOOL
  153. ('t', "text-checking", "text spell checking enabled", EINA_TRUE),
  154. ECORE_GETOPT_STORE_DEF_STR
  155. ('p', "policy-cookies", "Cookies policy:\n always - always accept,\n never - never accept,\n no-third-party - don't accept third-party cookies.", "no-third-party"),
  156. ECORE_GETOPT_VERSION
  157. ('V', "version"),
  158. ECORE_GETOPT_COPYRIGHT
  159. ('R', "copyright"),
  160. ECORE_GETOPT_HELP
  161. ('h', "help"),
  162. ECORE_GETOPT_SENTINEL
  163. }
  164. };
  165. static Browser_Window *window_create(Evas_Object* opener, const char *url, int width, int height, Eina_Bool view_mode);
  166. static Browser_Window *window_find_with_elm_window(Evas_Object *elm_window)
  167. {
  168. Eina_List *l;
  169. void *data;
  170. if (!elm_window)
  171. return NULL;
  172. EINA_LIST_FOREACH(windows, l, data) {
  173. Browser_Window *window = (Browser_Window *)data;
  174. if (window->elm_window == elm_window)
  175. return window;
  176. }
  177. return NULL;
  178. }
  179. static Browser_Window *window_find_with_ewk_view(Evas_Object *ewk_view)
  180. {
  181. Eina_List *l;
  182. void *data;
  183. if (!ewk_view)
  184. return NULL;
  185. EINA_LIST_FOREACH(windows, l, data) {
  186. Browser_Window *window = (Browser_Window *)data;
  187. if (window->ewk_view == ewk_view)
  188. return window;
  189. }
  190. return NULL;
  191. }
  192. static Eina_Bool
  193. on_tooltip_show(void *user_data)
  194. {
  195. Browser_Window *window = (Browser_Window *)user_data;
  196. window->tooltip.show_timer = NULL;
  197. elm_object_tooltip_show(window->elm_window);
  198. window->tooltip.shown = EINA_TRUE;
  199. return ECORE_CALLBACK_CANCEL;
  200. }
  201. static void
  202. window_tooltip_hide(Browser_Window *window)
  203. {
  204. if (window->tooltip.show_timer) {
  205. ecore_timer_del(window->tooltip.show_timer);
  206. window->tooltip.show_timer = NULL;
  207. }
  208. if (window->tooltip.shown) {
  209. elm_object_tooltip_hide(window->elm_window);
  210. window->tooltip.shown = EINA_FALSE;
  211. }
  212. }
  213. static void
  214. window_tooltip_update(Browser_Window *window)
  215. {
  216. window_tooltip_hide(window);
  217. if (window->tooltip.activated && window->tooltip.text_set)
  218. window->tooltip.show_timer = ecore_timer_add(TOOLTIP_DELAY_SECONDS, on_tooltip_show, window);
  219. }
  220. static void
  221. on_mouse_in(void *user_data, Evas *e, Evas_Object *ewk_view, void *event_info)
  222. {
  223. Browser_Window *window = (Browser_Window *)user_data;
  224. window->tooltip.activated = EINA_TRUE;
  225. window_tooltip_update(window);
  226. }
  227. static void
  228. on_mouse_move(void *user_data, Evas *e, Evas_Object *ewk_view, void *event_info)
  229. {
  230. window_tooltip_update((Browser_Window *)user_data);
  231. }
  232. static void
  233. on_mouse_out(void *user_data, Evas *e, Evas_Object *ewk_view, void *event_info)
  234. {
  235. Browser_Window *window = (Browser_Window *)user_data;
  236. window->tooltip.activated = EINA_FALSE;
  237. window_tooltip_update(window);
  238. }
  239. static void
  240. on_window_resize(void *user_data, Evas *e, Evas_Object *elm_window, void *event_info)
  241. {
  242. Browser_Window *window = (Browser_Window *)user_data;
  243. if (!window) {
  244. info("ERROR: window is NULL.");
  245. return;
  246. }
  247. if (window->context_menu.ewk_menu)
  248. ewk_context_menu_hide(window->context_menu.ewk_menu);
  249. if (window->popup.ewk_menu)
  250. ewk_popup_menu_close(window->popup.ewk_menu);
  251. if (window->popup.elm_menu)
  252. elm_menu_close(window->popup.elm_menu);
  253. }
  254. static void window_free(Browser_Window *window)
  255. {
  256. evas_object_event_callback_del(window->ewk_view, EVAS_CALLBACK_MOUSE_IN, on_mouse_in);
  257. evas_object_event_callback_del(window->ewk_view, EVAS_CALLBACK_MOUSE_OUT, on_mouse_out);
  258. evas_object_event_callback_del(window->ewk_view, EVAS_CALLBACK_MOUSE_MOVE, on_mouse_move);
  259. evas_object_event_callback_del(window->elm_window, EVAS_CALLBACK_RESIZE, on_window_resize);
  260. evas_object_del(window->ewk_view);
  261. /* The elm_win will take care of freeing its children */
  262. evas_object_del(window->elm_window);
  263. if (window->tooltip.show_timer)
  264. ecore_timer_del(window->tooltip.show_timer);
  265. if (window->color_selector.elm_selector_window)
  266. evas_object_del(window->color_selector.elm_selector_window);
  267. free(window);
  268. }
  269. static void window_close(Browser_Window *window)
  270. {
  271. windows = eina_list_remove(windows, window);
  272. window_free(window);
  273. if (!windows)
  274. elm_exit();
  275. }
  276. static void
  277. search_box_show(Browser_Window *window)
  278. {
  279. evas_object_size_hint_min_set(window->search.search_bar, SEARCH_FIELD_SIZE + 2 * SEARCH_BUTTON_SIZE, SEARCH_BUTTON_SIZE);
  280. evas_object_show(window->search.search_bar);
  281. evas_object_show(window->search.search_field);
  282. evas_object_show(window->search.backward_button);
  283. evas_object_show(window->search.forward_button);
  284. /* Grab focus from the view */
  285. evas_object_focus_set(window->ewk_view, EINA_FALSE);
  286. elm_object_focus_set(window->search.search_field, EINA_TRUE);
  287. }
  288. static void
  289. search_box_hide(Browser_Window *window)
  290. {
  291. ewk_view_text_find_highlight_clear(window->ewk_view);
  292. evas_object_size_hint_min_set(window->search.search_bar, SEARCH_FIELD_SIZE + 2 * SEARCH_BUTTON_SIZE, 0);
  293. evas_object_hide(window->search.search_bar);
  294. evas_object_hide(window->search.search_field);
  295. evas_object_hide(window->search.backward_button);
  296. evas_object_hide(window->search.forward_button);
  297. /* Give focus back to the view */
  298. elm_object_focus_set(window->search.search_field, EINA_FALSE);
  299. evas_object_focus_set(window->ewk_view, EINA_TRUE);
  300. }
  301. static void
  302. on_key_down(void *user_data, Evas *e, Evas_Object *ewk_view, void *event_info)
  303. {
  304. Browser_Window *window = (Browser_Window *)user_data;
  305. Evas_Event_Key_Down *ev = (Evas_Event_Key_Down*) event_info;
  306. static const char *encodings[] = {
  307. "ISO-8859-1",
  308. "UTF-8",
  309. NULL
  310. };
  311. static int currentEncoding = -1;
  312. Eina_Bool ctrlPressed = evas_key_modifier_is_set(evas_key_modifier_get(e), "Control");
  313. if (!strcmp(ev->key, "F1")) {
  314. info("Back (F1) was pressed");
  315. if (!ewk_view_back(ewk_view))
  316. info("Back ignored: No back history");
  317. } else if (!strcmp(ev->key, "F2")) {
  318. info("Forward (F2) was pressed");
  319. if (!ewk_view_forward(ewk_view))
  320. info("Forward ignored: No forward history");
  321. } else if (!strcmp(ev->key, "F3")) {
  322. currentEncoding = (currentEncoding + 1) % (sizeof(encodings) / sizeof(encodings[0]));
  323. info("Set encoding (F3) pressed. New encoding to %s", encodings[currentEncoding]);
  324. ewk_view_custom_encoding_set(ewk_view, encodings[currentEncoding]);
  325. } else if (!strcmp(ev->key, "F5")) {
  326. info("Reload (F5) was pressed, reloading.");
  327. ewk_view_reload(ewk_view);
  328. } else if (!strcmp(ev->key, "F6")) {
  329. info("Stop (F6) was pressed, stop loading.");
  330. ewk_view_stop(ewk_view);
  331. } else if (!strcmp(ev->key, "F7")) {
  332. Ewk_Pagination_Mode mode = ewk_view_pagination_mode_get(ewk_view);
  333. mode = (++mode) % (EWK_PAGINATION_MODE_BOTTOM_TO_TOP + 1);
  334. if (ewk_view_pagination_mode_set(ewk_view, mode))
  335. info("Change Pagination Mode (F7) was pressed, changed to: %d", mode);
  336. else
  337. info("Change Pagination Mode (F7) was pressed, but NOT changed!");
  338. } else if (!strcmp(ev->key, "F8")) {
  339. info("Create souce code window (F8) was pressed.");
  340. Browser_Window *window = window_create(ewk_view, ewk_view_url_get(ewk_view), 0, 0, EINA_TRUE);
  341. windows = eina_list_append(windows, window);
  342. } else if (!strcmp(ev->key, "F11")) {
  343. info("Fullscreen (F11) was pressed, toggling window/fullscreen.");
  344. elm_win_fullscreen_set(window->elm_window, !elm_win_fullscreen_get(window->elm_window));
  345. } else if (!strcmp(ev->key, "n") && ctrlPressed) {
  346. info("Create new window (Ctrl+n) was pressed.");
  347. Browser_Window *window = window_create(NULL, DEFAULT_URL, 0, 0, EINA_FALSE);
  348. // 0 equals default width and height.
  349. windows = eina_list_append(windows, window);
  350. } else if (!strcmp(ev->key, "i") && ctrlPressed) {
  351. info("Show Inspector (Ctrl+i) was pressed.");
  352. ewk_view_inspector_show(ewk_view);
  353. } else if (!strcmp(ev->key, "f") && ctrlPressed) {
  354. info("Show Search Box (Ctrl+f) was pressed.");
  355. search_box_show(window);
  356. } else if (!strcmp(ev->key, "Escape")) {
  357. if (evas_object_visible_get(window->search.search_bar))
  358. search_box_hide(window);
  359. else if (elm_win_fullscreen_get(window->elm_window))
  360. ewk_view_fullscreen_exit(ewk_view);
  361. } else if (ctrlPressed && (!strcmp(ev->key, "minus") || !strcmp(ev->key, "KP_Subtract"))) {
  362. if (zoom_level_set(ewk_view, window->current_zoom_level - 1))
  363. window->current_zoom_level--;
  364. info("Zoom out (Ctrl + '-') was pressed, zoom level became %.2f", zoomLevels[window->current_zoom_level]);
  365. } else if (ctrlPressed && (!strcmp(ev->key, "equal") || !strcmp(ev->key, "KP_Add"))) {
  366. if (zoom_level_set(ewk_view, window->current_zoom_level + 1))
  367. window->current_zoom_level++;
  368. info("Zoom in (Ctrl + '+') was pressed, zoom level became %.2f", zoomLevels[window->current_zoom_level]);
  369. } else if (ctrlPressed && !strcmp(ev->key, "0")) {
  370. if (zoom_level_set(ewk_view, DEFAULT_ZOOM_LEVEL))
  371. window->current_zoom_level = DEFAULT_ZOOM_LEVEL;
  372. info("Zoom to default (Ctrl + '0') was pressed, zoom level became %.2f", zoomLevels[window->current_zoom_level]);
  373. }
  374. }
  375. static void
  376. view_focus_set(Browser_Window *window, Eina_Bool focus)
  377. {
  378. /* We steal focus away from elm's focus model and start to do things
  379. * manually here, so elm now has no clue what's up. Tell elm that its
  380. * toplevel widget is to be unfocused so elm gives up the focus */
  381. elm_object_focus_set(elm_object_top_widget_get(window->elm_window), EINA_FALSE);
  382. evas_object_focus_set(window->ewk_view, focus);
  383. }
  384. static void
  385. on_mouse_down(void *user_data, Evas *e, Evas_Object *ewk_view, void *event_info)
  386. {
  387. Browser_Window *window = (Browser_Window *)user_data;
  388. Evas_Event_Mouse_Down *ev = (Evas_Event_Mouse_Down *)event_info;
  389. /* Clear selection from the URL bar */
  390. elm_entry_select_none(window->url_bar);
  391. if (ev->button == 1)
  392. view_focus_set(window, EINA_TRUE);
  393. else if (ev->button == 2)
  394. view_focus_set(window, !evas_object_focus_get(ewk_view));
  395. }
  396. static void
  397. title_set(Evas_Object *elm_window, const char *title, int progress)
  398. {
  399. Eina_Strbuf *buffer;
  400. if (!title || !*title) {
  401. elm_win_title_set(elm_window, APP_NAME);
  402. return;
  403. }
  404. buffer = eina_strbuf_new();
  405. if (progress < 100)
  406. eina_strbuf_append_printf(buffer, "%s (%d%%) - %s", title, progress, APP_NAME);
  407. else
  408. eina_strbuf_append_printf(buffer, "%s - %s", title, APP_NAME);
  409. elm_win_title_set(elm_window, eina_strbuf_string_get(buffer));
  410. eina_strbuf_free(buffer);
  411. }
  412. static void
  413. on_title_changed(void *user_data, Evas_Object *ewk_view, void *event_info)
  414. {
  415. Browser_Window *window = (Browser_Window *)user_data;
  416. const char *title = (const char *)event_info;
  417. title_set(window->elm_window, title, 100);
  418. }
  419. static void
  420. on_url_changed(void *user_data, Evas_Object *ewk_view, void *event_info)
  421. {
  422. Browser_Window *window = (Browser_Window *)user_data;
  423. char *url = elm_entry_utf8_to_markup(ewk_view_url_get(window->ewk_view));
  424. elm_entry_entry_set(window->url_bar, url);
  425. free(url);
  426. search_box_hide(window);
  427. }
  428. static void
  429. on_back_forward_list_changed(void *user_data, Evas_Object *ewk_view, void *event_info)
  430. {
  431. Browser_Window *window = (Browser_Window *)user_data;
  432. /* Update navigation buttons state */
  433. elm_object_disabled_set(window->back_button, !ewk_view_back_possible(ewk_view));
  434. elm_object_disabled_set(window->forward_button, !ewk_view_forward_possible(ewk_view));
  435. }
  436. static void
  437. on_progress(void *user_data, Evas_Object *ewk_view, void *event_info)
  438. {
  439. Browser_Window *window = (Browser_Window *)user_data;
  440. double progress = *(double *)event_info;
  441. title_set(window->elm_window, ewk_view_title_get(window->ewk_view), progress * 100);
  442. }
  443. static void
  444. on_error(void *user_data, Evas_Object *ewk_view, void *event_info)
  445. {
  446. Eina_Strbuf *buffer;
  447. const Ewk_Error *error = (const Ewk_Error *)event_info;
  448. /* This is a cancellation, do not display the error page */
  449. if (ewk_error_cancellation_get(error))
  450. return;
  451. buffer = eina_strbuf_new();
  452. eina_strbuf_append_printf(buffer, "<html><body><div style=\"color:#ff0000\">ERROR!</div><br><div>Code: %d<br>Description: %s<br>URL: %s</div></body</html>",
  453. ewk_error_code_get(error), ewk_error_description_get(error), ewk_error_url_get(error));
  454. ewk_view_html_string_load(ewk_view, eina_strbuf_string_get(buffer), 0, ewk_error_url_get(error));
  455. eina_strbuf_free(buffer);
  456. }
  457. static void
  458. on_download_request(void *user_data, Evas_Object *ewk_view, void *event_info)
  459. {
  460. Ewk_Download_Job *download = (Ewk_Download_Job *)event_info;
  461. // FIXME: The destination folder should be selected by the user but we set it to '/tmp' for now.
  462. Eina_Strbuf *destination_path = eina_strbuf_new();
  463. const char *suggested_name = ewk_download_job_suggested_filename_get(download);
  464. if (suggested_name && *suggested_name)
  465. eina_strbuf_append_printf(destination_path, "/tmp/%s", suggested_name);
  466. else {
  467. // Generate a unique file name since no name was suggested.
  468. char unique_path[] = "/tmp/downloaded-file.XXXXXX";
  469. eina_strbuf_append(destination_path, mktemp(unique_path));
  470. }
  471. ewk_download_job_destination_set(download, eina_strbuf_string_get(destination_path));
  472. info("Downloading: %s", eina_strbuf_string_get(destination_path));
  473. eina_strbuf_free(destination_path);
  474. }
  475. static void on_filepicker_parent_deletion(void *user_data, Evas *evas, Evas_Object *elm_window, void *event);
  476. static void close_file_picker(File_Selector_Data *fs_data)
  477. {
  478. evas_object_event_callback_del(fs_data->parent->elm_window, EVAS_CALLBACK_DEL, on_filepicker_parent_deletion);
  479. evas_object_del(fs_data->elm_window);
  480. ewk_object_unref(fs_data->request);
  481. free(fs_data);
  482. }
  483. static void
  484. on_filepicker_parent_deletion(void *user_data, Evas *evas, Evas_Object *elm_window, void *event)
  485. {
  486. close_file_picker((File_Selector_Data *)user_data);
  487. }
  488. static void
  489. on_filepicker_deletion(void *user_data, Evas_Object *elm_window, void *event_info)
  490. {
  491. close_file_picker((File_Selector_Data *)user_data);
  492. }
  493. static void
  494. on_fileselector_done(void *user_data, Evas_Object *file_selector, void *event_info)
  495. {
  496. File_Selector_Data *fs_data = (File_Selector_Data *)user_data;
  497. const char *selected = (const char *)event_info;
  498. if (selected && *selected)
  499. ewk_file_chooser_request_file_choose(fs_data->request, selected);
  500. close_file_picker(fs_data);
  501. }
  502. static void
  503. on_file_chooser_request(void *user_data, Evas_Object *ewk_view, void *event_info)
  504. {
  505. Evas_Object *bg;
  506. Browser_Window *window = (Browser_Window *)user_data;
  507. Ewk_File_Chooser_Request *request = (Ewk_File_Chooser_Request *)event_info;
  508. // Show basic file picker which does not currently support multiple files
  509. // or MIME type filtering.
  510. Evas_Object *elm_window = elm_win_add(window->elm_window, "file-picker-window", ELM_WIN_DIALOG_BASIC);
  511. elm_win_title_set(elm_window, "File picker");
  512. elm_win_modal_set(elm_window, EINA_TRUE);
  513. bg = elm_bg_add(elm_window);
  514. evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
  515. elm_win_resize_object_add(elm_window, bg);
  516. evas_object_show(bg);
  517. File_Selector_Data *fs_data = (File_Selector_Data *)malloc(sizeof(File_Selector_Data));
  518. fs_data->parent = window;
  519. fs_data->elm_window = elm_window;
  520. fs_data->request = ewk_object_ref(request);
  521. evas_object_smart_callback_add(elm_window, "delete,request", on_filepicker_deletion, fs_data);
  522. evas_object_event_callback_add(window->elm_window, EVAS_CALLBACK_DEL, on_filepicker_parent_deletion, fs_data);
  523. Evas_Object *file_selector = elm_fileselector_add(elm_window);
  524. const char *home_path = getenv("HOME");
  525. elm_fileselector_path_set(file_selector, home_path ? home_path : "/home");
  526. evas_object_size_hint_weight_set(file_selector, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
  527. elm_win_resize_object_add(elm_window, file_selector);
  528. evas_object_show(file_selector);
  529. evas_object_smart_callback_add(file_selector, "done", on_fileselector_done, fs_data);
  530. evas_object_resize(elm_window, 400, 400);
  531. elm_win_center(elm_window, EINA_TRUE, EINA_TRUE);
  532. evas_object_show(elm_window);
  533. }
  534. static void
  535. on_download_finished(void *user_data, Evas_Object *ewk_view, void *event_info)
  536. {
  537. Ewk_Download_Job *download = (Ewk_Download_Job *)event_info;
  538. info("Download finished: %s", ewk_download_job_destination_get(download));
  539. }
  540. static void
  541. on_download_failed(void *user_data, Evas_Object *ewk_view, void *event_info)
  542. {
  543. info("Download failed!");
  544. }
  545. static void
  546. on_color_changed(void *data, Evas_Object *obj, void *event_info)
  547. {
  548. int r, g, b, a;
  549. elm_colorselector_color_get(obj, &r, &g, &b, &a);
  550. evas_object_color_set(data, r, g, b, a);
  551. }
  552. static void
  553. on_color_item_selected(void *data, Evas_Object *obj, void *event_info)
  554. {
  555. int r, g, b, a;
  556. Elm_Object_Item *color_item = (Elm_Object_Item *)event_info;
  557. elm_colorselector_palette_item_color_get(color_item, &r, &g, &b, &a);
  558. evas_object_color_set(data, r, g, b, a);
  559. }
  560. static void
  561. on_color_picker_ok_clicked(void *data, Evas_Object *obj, void *event_info)
  562. {
  563. int r, g, b, a;
  564. Color_Selector *color_selector = (Color_Selector *)data;
  565. elm_colorselector_color_get(color_selector->elm_selector, &r, &g, &b, &a);
  566. ewk_color_picker_color_set(color_selector->ewk_picker, r, g, b, a);
  567. }
  568. static void
  569. on_color_picker_cancel_clicked(void *data, Evas_Object *obj, void *event_info)
  570. {
  571. int r, g, b, a;
  572. ewk_color_picker_color_get(data, &r, &g, &b, &a);
  573. ewk_color_picker_color_set(data, r, g, b, a);
  574. }
  575. static Eina_Bool
  576. on_color_picker_dismiss(Ewk_View_Smart_Data *sd)
  577. {
  578. Browser_Window *window = window_find_with_ewk_view(sd->self);
  579. evas_object_del(window->color_selector.elm_selector_window);
  580. window->color_selector.elm_selector_window = NULL;
  581. return EINA_TRUE;
  582. }
  583. static Eina_Bool
  584. on_color_picker_request(Ewk_View_Smart_Data *sd, Ewk_Color_Picker *color_picker)
  585. {
  586. int r, g, b, a;
  587. Evas_Object *background, *rect, *box, *button_box, *rect_frame, *cs_frame, *ok_button, *cancel_button;
  588. Browser_Window *window = window_find_with_ewk_view(sd->self);
  589. window->color_selector.elm_selector_window = elm_win_add(window->elm_window, "color selector", ELM_WIN_BASIC);
  590. window->color_selector.ewk_picker = color_picker;
  591. elm_win_title_set(window->color_selector.elm_selector_window, "Color selector");
  592. /* Show color view */
  593. background = elm_bg_add(window->color_selector.elm_selector_window);
  594. evas_object_size_hint_weight_set(background, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
  595. elm_win_resize_object_add(window->color_selector.elm_selector_window, background);
  596. evas_object_show(background);
  597. box = elm_box_add(window->color_selector.elm_selector_window);
  598. evas_object_size_hint_weight_set(box, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
  599. elm_win_resize_object_add(window->color_selector.elm_selector_window, box);
  600. evas_object_show(box);
  601. rect_frame = elm_frame_add(window->color_selector.elm_selector_window);
  602. evas_object_size_hint_weight_set(rect_frame, EVAS_HINT_EXPAND, 0.3);
  603. evas_object_size_hint_align_set(rect_frame, EVAS_HINT_FILL, EVAS_HINT_FILL);
  604. elm_object_text_set(rect_frame, "Color View");
  605. elm_box_pack_end(box, rect_frame);
  606. evas_object_show(rect_frame);
  607. rect = evas_object_rectangle_add(evas_object_evas_get(window->color_selector.elm_selector_window));
  608. elm_object_content_set(rect_frame, rect);
  609. ewk_color_picker_color_get(window->color_selector.ewk_picker, &r, &g, &b, &a);
  610. evas_object_color_set(rect, r, g, b, a);
  611. evas_object_show(rect);
  612. /* Show color selector */
  613. cs_frame = elm_frame_add(window->color_selector.elm_selector_window);
  614. evas_object_size_hint_weight_set(cs_frame, EVAS_HINT_EXPAND, 0.7);
  615. evas_object_size_hint_align_set(cs_frame, EVAS_HINT_FILL, EVAS_HINT_FILL);
  616. elm_object_text_set(cs_frame, "Color Selector");
  617. elm_box_pack_end(box, cs_frame);
  618. evas_object_show(cs_frame);
  619. window->color_selector.elm_selector = elm_colorselector_add(window->color_selector.elm_selector_window);
  620. elm_object_content_set(cs_frame, window->color_selector.elm_selector);
  621. evas_object_show(window->color_selector.elm_selector);
  622. /* OK, Cancel Buttons */
  623. button_box = elm_box_add(window->color_selector.elm_selector_window);
  624. elm_box_horizontal_set(button_box, EINA_TRUE);
  625. evas_object_size_hint_min_set(button_box, 200, 50);
  626. elm_box_pack_end(box, button_box);
  627. evas_object_show(button_box);
  628. ok_button = elm_button_add(window->color_selector.elm_selector_window);
  629. elm_object_text_set(ok_button, "OK");
  630. elm_box_pack_end(button_box, ok_button);
  631. evas_object_show(ok_button);
  632. cancel_button = elm_button_add(window->color_selector.elm_selector_window);
  633. elm_object_text_set(cancel_button, "Cancel");
  634. elm_box_pack_end(button_box, cancel_button);
  635. evas_object_show(cancel_button);
  636. evas_object_smart_callback_add(ok_button, "clicked", on_color_picker_ok_clicked, &(window->color_selector));
  637. evas_object_smart_callback_add(cancel_button, "clicked", on_color_picker_cancel_clicked, window->color_selector.ewk_picker);
  638. evas_object_smart_callback_add(window->color_selector.elm_selector_window, "delete,request", on_color_picker_cancel_clicked, window->color_selector.ewk_picker);
  639. evas_object_smart_callback_add(window->color_selector.elm_selector, "changed", on_color_changed, rect);
  640. evas_object_smart_callback_add(window->color_selector.elm_selector, "color,item,selected", on_color_item_selected, rect);
  641. elm_win_center(window->color_selector.elm_selector_window, EINA_TRUE, EINA_TRUE);
  642. evas_object_resize(window->color_selector.elm_selector_window, 350, 500);
  643. evas_object_show(window->color_selector.elm_selector_window);
  644. return EINA_TRUE;
  645. }
  646. static void
  647. update_view_favicon(Browser_Window *window, Evas_Object *icon)
  648. {
  649. /* Remove previous icon from URL bar */
  650. Evas_Object *old_icon = elm_object_part_content_unset(window->url_bar, "icon");
  651. if (old_icon) {
  652. evas_object_unref(old_icon);
  653. evas_object_del(old_icon);
  654. }
  655. /* Show new icon in URL bar */
  656. if (icon) {
  657. /* Workaround for icon display bug:
  658. * http://trac.enlightenment.org/e/ticket/1616 */
  659. evas_object_size_hint_min_set(icon, 48, 24);
  660. evas_object_image_filled_set(icon, EINA_FALSE);
  661. evas_object_image_fill_set(icon, 24, 0, 24, 24);
  662. elm_object_part_content_set(window->url_bar, "icon", icon);
  663. evas_object_ref(icon);
  664. }
  665. }
  666. static void
  667. on_view_favicon_changed(void *user_data, Evas_Object *ewk_view, void *event_info)
  668. {
  669. Browser_Window *window = (Browser_Window *)user_data;
  670. Evas_Object* favicon = ewk_view_favicon_get(ewk_view);
  671. update_view_favicon(window, favicon);
  672. if (favicon)
  673. evas_object_unref(favicon);
  674. }
  675. static int
  676. quit(Eina_Bool success, const char *msg)
  677. {
  678. ewk_shutdown();
  679. elm_shutdown();
  680. if (msg)
  681. fputs(msg, (success) ? stdout : stderr);
  682. if (!success)
  683. return EXIT_FAILURE;
  684. return EXIT_SUCCESS;
  685. }
  686. static void
  687. on_url_bar_activated(void *user_data, Evas_Object *url_bar, void *event_info)
  688. {
  689. Browser_Window *window = (Browser_Window *)user_data;
  690. const char *markup_url = elm_entry_entry_get(url_bar);
  691. char *user_url = elm_entry_markup_to_utf8(markup_url);
  692. char *url = url_from_user_input(user_url);
  693. ewk_view_url_set(window->ewk_view, url);
  694. free(user_url);
  695. free(url);
  696. /* Give focus back to the view */
  697. view_focus_set(window, EINA_TRUE);
  698. }
  699. static void
  700. on_url_bar_clicked(void *user_data, Evas_Object *url_bar, void *event_info)
  701. {
  702. Browser_Window *window = (Browser_Window *)user_data;
  703. /* Grab focus from the view */
  704. evas_object_focus_set(window->ewk_view, EINA_FALSE);
  705. elm_object_focus_set(url_bar, EINA_TRUE);
  706. }
  707. static void
  708. on_search_field_aborted(void *user_data, Evas_Object *search_field, void *event_info)
  709. {
  710. Browser_Window *window = (Browser_Window *)user_data;
  711. search_box_hide(window);
  712. /* Give focus back to the view */
  713. view_focus_set(window, EINA_TRUE);
  714. }
  715. static void
  716. on_search_field_activated(void *user_data, Evas_Object *search_field, void *event_info)
  717. {
  718. Browser_Window *window = (Browser_Window *)user_data;
  719. const char *markup_text = elm_entry_entry_get(search_field);
  720. char *text = elm_entry_markup_to_utf8(markup_text);
  721. ewk_view_text_find(window->ewk_view, text, DEFAULT_SEARCH_FLAGS, MAX_SEARCH_COUNT);
  722. free(text);
  723. /* Grab focus from the view */
  724. evas_object_focus_set(window->ewk_view, EINA_FALSE);
  725. elm_object_focus_set(search_field, EINA_TRUE);
  726. }
  727. static void
  728. on_search_field_clicked(void *user_data, Evas_Object *search_field, void *event_info)
  729. {
  730. Browser_Window *window = (Browser_Window *)user_data;
  731. /* Grab focus from the view */
  732. evas_object_focus_set(window->ewk_view, EINA_FALSE);
  733. elm_object_focus_set(search_field, EINA_TRUE);
  734. }
  735. static void
  736. on_back_button_clicked(void *user_data, Evas_Object *back_button, void *event_info)
  737. {
  738. Browser_Window *window = (Browser_Window *)user_data;
  739. ewk_view_back(window->ewk_view);
  740. /* Update back button state */
  741. elm_object_disabled_set(back_button, !ewk_view_back_possible(window->ewk_view));
  742. }
  743. static void
  744. on_forward_button_clicked(void *user_data, Evas_Object *forward_button, void *event_info)
  745. {
  746. Browser_Window *window = (Browser_Window *)user_data;
  747. ewk_view_forward(window->ewk_view);
  748. /* Update forward button state */
  749. elm_object_disabled_set(forward_button, !ewk_view_forward_possible(window->ewk_view));
  750. }
  751. static void
  752. on_search_backward_button_clicked(void *user_data, Evas_Object *search_backward_button, void *event_info)
  753. {
  754. Browser_Window *window = (Browser_Window *)user_data;
  755. char *text = elm_entry_markup_to_utf8(elm_entry_entry_get(window->search.search_field));
  756. ewk_view_text_find(window->ewk_view, text, DEFAULT_SEARCH_FLAGS | EWK_FIND_OPTIONS_BACKWARDS, MAX_SEARCH_COUNT);
  757. free(text);
  758. }
  759. static void
  760. on_search_forward_button_clicked(void *user_data, Evas_Object *search_forward_button, void *event_info)
  761. {
  762. Browser_Window *window = (Browser_Window *)user_data;
  763. char *text = elm_entry_markup_to_utf8(elm_entry_entry_get(window->search.search_field));
  764. ewk_view_text_find(window->ewk_view, text, DEFAULT_SEARCH_FLAGS, MAX_SEARCH_COUNT);
  765. free(text);
  766. }
  767. static void
  768. on_refresh_button_clicked(void *user_data, Evas_Object *refresh_button, void *event_info)
  769. {
  770. Browser_Window *window = (Browser_Window *)user_data;
  771. Evas *evas = evas_object_evas_get(refresh_button);
  772. Eina_Bool ctrlPressed = evas_key_modifier_is_set(evas_key_modifier_get(evas), "Control");
  773. if (ctrlPressed) {
  774. info("Reloading and bypassing cache...");
  775. ewk_view_reload_bypass_cache(window->ewk_view);
  776. } else {
  777. info("Reloading...");
  778. ewk_view_reload(window->ewk_view);
  779. }
  780. }
  781. static void
  782. quit_event_loop(void *user_data, Evas_Object *obj, void *event_info)
  783. {
  784. ecore_main_loop_quit();
  785. }
  786. static void
  787. on_ok_clicked(void *user_data, Evas_Object *obj, void *event_info)
  788. {
  789. Eina_Bool *confirmed = (Eina_Bool *)user_data;
  790. *confirmed = EINA_TRUE;
  791. ecore_main_loop_quit();
  792. }
  793. static void
  794. on_javascript_alert(Ewk_View_Smart_Data *smartData, const char *message)
  795. {
  796. Browser_Window *window = window_find_with_ewk_view(smartData->self);
  797. Evas_Object *alert_popup = elm_popup_add(window->elm_window);
  798. evas_object_size_hint_weight_set(alert_popup, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
  799. elm_object_text_set(alert_popup, message);
  800. elm_object_part_text_set(alert_popup, "title,text", "Alert");
  801. /* Popup buttons */
  802. Evas_Object *button = elm_button_add(alert_popup);
  803. elm_object_text_set(button, "OK");
  804. elm_object_part_content_set(alert_popup, "button1", button);
  805. evas_object_smart_callback_add(button, "clicked", quit_event_loop, NULL);
  806. elm_object_focus_set(button, EINA_TRUE);
  807. evas_object_show(alert_popup);
  808. /* Make modal */
  809. ecore_main_loop_begin();
  810. evas_object_del(alert_popup);
  811. }
  812. static Eina_Bool
  813. on_javascript_confirm(Ewk_View_Smart_Data *smartData, const char *message)
  814. {
  815. Browser_Window *window = window_find_with_ewk_view(smartData->self);
  816. Eina_Bool ok = EINA_FALSE;
  817. Evas_Object *confirm_popup = elm_popup_add(window->elm_window);
  818. evas_object_size_hint_weight_set(confirm_popup, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
  819. elm_object_text_set(confirm_popup, message);
  820. elm_object_part_text_set(confirm_popup, "title,text", "Confirmation");
  821. /* Popup buttons */
  822. Evas_Object *cancel_button = elm_button_add(confirm_popup);
  823. elm_object_text_set(cancel_button, "Cancel");
  824. elm_object_part_content_set(confirm_popup, "button1", cancel_button);
  825. evas_object_smart_callback_add(cancel_button, "clicked", quit_event_loop, NULL);
  826. Evas_Object *ok_button = elm_button_add(confirm_popup);
  827. elm_object_text_set(ok_button, "OK");
  828. elm_object_part_content_set(confirm_popup, "button2", ok_button);
  829. evas_object_smart_callback_add(ok_button, "clicked", on_ok_clicked, &ok);
  830. elm_object_focus_set(ok_button, EINA_TRUE);
  831. evas_object_show(confirm_popup);
  832. /* Make modal */
  833. ecore_main_loop_begin();
  834. evas_object_del(confirm_popup);
  835. return ok;
  836. }
  837. static const char *
  838. on_javascript_prompt(Ewk_View_Smart_Data *smartData, const char *message, const char *default_value)
  839. {
  840. Browser_Window *window = window_find_with_ewk_view(smartData->self);
  841. Eina_Bool ok = EINA_FALSE;
  842. Evas_Object *prompt_popup = elm_popup_add(window->elm_window);
  843. evas_object_size_hint_weight_set(prompt_popup, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
  844. elm_object_part_text_set(prompt_popup, "title,text", "Prompt");
  845. /* Popup Content */
  846. Evas_Object *box = elm_box_add(window->elm_window);
  847. elm_box_padding_set(box, 0, 4);
  848. evas_object_size_hint_weight_set(box, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
  849. evas_object_size_hint_align_set(box, EVAS_HINT_FILL, EVAS_HINT_FILL);
  850. evas_object_show(box);
  851. Evas_Object *prompt = elm_label_add(window->elm_window);
  852. elm_object_text_set(prompt, message);
  853. evas_object_size_hint_weight_set(prompt, EVAS_HINT_EXPAND, 0.0);
  854. evas_object_size_hint_align_set(prompt, EVAS_HINT_FILL, 0.5);
  855. elm_box_pack_end(box, prompt);
  856. evas_object_show(prompt);
  857. Evas_Object *entry = elm_entry_add(window->elm_window);
  858. elm_entry_scrollable_set(entry, EINA_TRUE);
  859. elm_entry_single_line_set(entry, EINA_TRUE);
  860. elm_entry_text_style_user_push(entry, "DEFAULT='font_size=18'");
  861. elm_entry_entry_set(entry, default_value ? default_value : "");
  862. elm_entry_select_all(entry);
  863. evas_object_size_hint_weight_set(entry, EVAS_HINT_EXPAND, 0.0);
  864. evas_object_size_hint_align_set(entry, EVAS_HINT_FILL, 0.5);
  865. elm_box_pack_end(box, entry);
  866. elm_object_focus_set(entry, EINA_TRUE);
  867. evas_object_show(entry);
  868. elm_object_content_set(prompt_popup, box);
  869. /* Popup buttons */
  870. Evas_Object *cancel_button = elm_button_add(prompt_popup);
  871. elm_object_text_set(cancel_button, "Cancel");
  872. elm_object_part_content_set(prompt_popup, "button1", cancel_button);
  873. evas_object_smart_callback_add(cancel_button, "clicked", quit_event_loop, NULL);
  874. Evas_Object *ok_button = elm_button_add(prompt_popup);
  875. elm_object_text_set(ok_button, "OK");
  876. elm_object_part_content_set(prompt_popup, "button2", ok_button);
  877. evas_object_smart_callback_add(ok_button, "clicked", on_ok_clicked, &ok);
  878. evas_object_show(prompt_popup);
  879. /* Make modal */
  880. ecore_main_loop_begin();
  881. /* The return string need to be stringshared */
  882. const char *prompt_text = ok ? eina_stringshare_add(elm_entry_entry_get(entry)) : NULL;
  883. evas_object_del(prompt_popup);
  884. return prompt_text;
  885. }
  886. static void
  887. on_popup_menu_discarded(void *user_data, Evas_Object *obj, void *event_info)
  888. {
  889. // The user clicked outside the menu to discard it.
  890. info("Popup menu was discarded.");
  891. Browser_Window *window = (Browser_Window *)user_data;
  892. ewk_popup_menu_close(window->popup.ewk_menu);
  893. }
  894. static void
  895. on_popup_menu_item_clicked(void *user_data, Evas_Object *obj, void *event_info)
  896. {
  897. Browser_Window *window = (Browser_Window *)user_data;
  898. Elm_Object_Item *item = (Elm_Object_Item *)event_info;
  899. info("Selected popup menu index: %u", elm_menu_item_index_get(item));
  900. ewk_popup_menu_selected_index_set(window->popup.ewk_menu, elm_menu_item_index_get(item));
  901. // Close popup menu.
  902. ewk_popup_menu_close(window->popup.ewk_menu);
  903. }
  904. static void
  905. popup_menu_populate(Evas_Object *elm_menu, Ewk_Popup_Menu *ewk_menu, void *user_data)
  906. {
  907. const Eina_List* ewk_items = ewk_popup_menu_items_get(ewk_menu);
  908. void *data;
  909. const Eina_List *l;
  910. EINA_LIST_FOREACH(ewk_items, l, data) {
  911. Ewk_Popup_Menu_Item *ewk_item = (Ewk_Popup_Menu_Item *)data;
  912. switch (ewk_popup_menu_item_type_get(ewk_item)) {
  913. case EWK_POPUP_MENU_SEPARATOR:
  914. elm_menu_item_separator_add(elm_menu, NULL);
  915. break;
  916. case EWK_POPUP_MENU_ITEM:
  917. if (ewk_popup_menu_item_is_label_get(ewk_item)) {
  918. Elm_Object_Item *item = elm_menu_item_add(elm_menu, NULL, NULL, ewk_popup_menu_item_text_get(ewk_item), NULL, NULL);
  919. elm_object_item_disabled_set(item, EINA_TRUE);
  920. } else {
  921. Elm_Object_Item *item = elm_menu_item_add(elm_menu, NULL, NULL, ewk_popup_menu_item_text_get(ewk_item), on_popup_menu_item_clicked, user_data);
  922. const char *tooltip_text = ewk_popup_menu_item_tooltip_get(ewk_item);
  923. if (tooltip_text && tooltip_text[0] != '\0')
  924. elm_object_item_tooltip_text_set(item, tooltip_text);
  925. elm_object_item_disabled_set(item, !ewk_popup_menu_item_enabled_get(ewk_item));
  926. elm_menu_item_selected_set(item, ewk_popup_menu_item_selected_get(ewk_item));
  927. }
  928. break;
  929. default:
  930. info("Unrecognized popup menu item type!");
  931. break;
  932. }
  933. }
  934. }
  935. static Eina_Bool
  936. on_popup_menu_show(Ewk_View_Smart_Data *smartData, Eina_Rectangle rect, Ewk_Text_Direction text_direction, double page_scale_factor, Ewk_Popup_Menu *ewk_menu)
  937. {
  938. Browser_Window *window = window_find_with_ewk_view(smartData->self);
  939. if (window->popup.elm_menu)
  940. evas_object_del(window->popup.elm_menu);
  941. window->popup.elm_menu = elm_menu_add(window->elm_window);
  942. window->popup.ewk_menu = ewk_menu;
  943. evas_object_smart_callback_add(window->popup.elm_menu, "clicked", on_popup_menu_discarded, window);
  944. popup_menu_populate(window->popup.elm_menu, ewk_menu, window);
  945. info("Showing popup menu at (%d, %d)", rect.x, rect.y);
  946. elm_menu_move(window->popup.elm_menu, rect.x, rect.y);
  947. evas_object_show(window->popup.elm_menu);
  948. return EINA_TRUE;
  949. }
  950. static Eina_Bool
  951. on_popup_menu_hide(Ewk_View_Smart_Data *smartData)
  952. {
  953. Browser_Window *window = window_find_with_ewk_view(smartData->self);
  954. if (!window->popup.elm_menu)
  955. return EINA_FALSE;
  956. elm_menu_close(window->popup.elm_menu);
  957. return EINA_TRUE;
  958. }
  959. static Eina_Bool on_window_geometry_get(Ewk_View_Smart_Data *sd, Evas_Coord *x, Evas_Coord *y, Evas_Coord *width, Evas_Coord *height)
  960. {
  961. Browser_Window *window = window_find_with_ewk_view(sd->self);
  962. evas_object_geometry_get(window->elm_window, x, y, width, height);
  963. return EINA_TRUE;
  964. }
  965. static Eina_Bool on_window_geometry_set(Ewk_View_Smart_Data *sd, Evas_Coord x, Evas_Coord y, Evas_Coord width, Evas_Coord height)
  966. {
  967. Browser_Window *window = window_find_with_ewk_view(sd->self);
  968. evas_object_move(window->elm_window, x, y);
  969. evas_object_resize(window->elm_window, width, height);
  970. return EINA_TRUE;
  971. }
  972. typedef struct {
  973. Evas_Object *ewk_view;
  974. Evas_Object *permission_popup;
  975. } PermissionData;
  976. static void
  977. on_fullscreen_accept(void *user_data, Evas_Object *obj, void *event_info)
  978. {
  979. PermissionData *permission_data = (PermissionData *)user_data;
  980. evas_object_del(permission_data->permission_popup);
  981. evas_object_focus_set(permission_data->ewk_view, EINA_TRUE);
  982. free(permission_data);
  983. }
  984. static void
  985. on_fullscreen_deny(void *user_data, Evas_Object *obj, void *event_info)
  986. {
  987. PermissionData *permission_data = (PermissionData *)user_data;
  988. ewk_view_fullscreen_exit(permission_data->ewk_view);
  989. evas_object_del(permission_data->permission_popup);
  990. evas_object_focus_set(permission_data->ewk_view, EINA_TRUE);
  991. free(permission_data);
  992. }
  993. static Eina_Bool on_fullscreen_enter(Ewk_View_Smart_Data *sd, Ewk_Security_Origin *origin)
  994. {
  995. Browser_Window *window = window_find_with_ewk_view(sd->self);
  996. /* Go fullscreen */
  997. elm_win_fullscreen_set(window->elm_window, EINA_TRUE);
  998. /* Show user popup */
  999. Evas_Object *permission_popup = elm_popup_add(window->elm_window);
  1000. evas_object_size_hint_weight_set(permission_popup, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
  1001. Eina_Strbuf *message = eina_strbuf_new();
  1002. eina_strbuf_append_printf(message, "%s is now fullscreen.<br>Press ESC at any time to exit fullscreen.<br>Allow fullscreen?", ewk_security_origin_host_get(origin));
  1003. elm_object_text_set(permission_popup, eina_strbuf_string_get(message));
  1004. eina_strbuf_free(message);
  1005. elm_object_part_text_set(permission_popup, "title,text", "Fullscreen Permission");
  1006. /* Popup buttons */
  1007. PermissionData *permission_data = (PermissionData *)malloc(sizeof(PermissionData));
  1008. permission_data->ewk_view = window->ewk_view;
  1009. permission_data->permission_popup = permission_popup;
  1010. Evas_Object *accept_button = elm_button_add(permission_popup);
  1011. elm_object_text_set(accept_button, "Accept");
  1012. elm_object_part_content_set(permission_popup, "button1", accept_button);
  1013. evas_object_smart_callback_add(accept_button, "clicked", on_fullscreen_accept, permission_data);
  1014. Evas_Object *deny_button = elm_button_add(permission_popup);
  1015. elm_object_text_set(deny_button, "Deny");
  1016. elm_object_part_content_set(permission_popup, "button2", deny_button);
  1017. evas_object_smart_callback_add(deny_button, "clicked", on_fullscreen_deny, permission_data);
  1018. evas_object_show(permission_popup);
  1019. return EINA_TRUE;
  1020. }
  1021. static Eina_Bool on_fullscreen_exit(Ewk_View_Smart_Data *sd)
  1022. {
  1023. Browser_Window *window = window_find_with_ewk_view(sd->self);
  1024. elm_win_fullscreen_set(window->elm_window, EINA_FALSE);
  1025. return EINA_TRUE;
  1026. }
  1027. static Evas_Object *
  1028. on_window_create(Ewk_View_Smart_Data *smartData, const char *url, const Ewk_Window_Features *window_features)
  1029. {
  1030. int x = 0;
  1031. int y = 0;
  1032. int width = 0;
  1033. int height = 0;
  1034. ewk_window_features_geometry_get(window_features, &x, &y, &width, &height);
  1035. if (!width)
  1036. width = window_width;
  1037. if (!height)
  1038. height = window_height;
  1039. Browser_Window *window = window_create(smartData->self, url, width, height, EINA_FALSE);
  1040. Evas_Object *new_view = window->ewk_view;
  1041. windows = eina_list_append(windows, window);
  1042. info("minibrowser: location(%d,%d) size=(%d,%d) url=%s", x, y, width, height, url);
  1043. return new_view;
  1044. }
  1045. static void
  1046. on_window_close(Ewk_View_Smart_Data *smartData)
  1047. {
  1048. Browser_Window *window = window_find_with_ewk_view(smartData->self);
  1049. window_close(window);
  1050. }
  1051. static void
  1052. context_menu_item_selected_cb(void *data, Evas_Object *obj, void *event_info)
  1053. {
  1054. if (!data) {
  1055. info("ERROR: context menu callback data is NULL.");
  1056. return;
  1057. }
  1058. Ewk_Context_Menu_Item *ewk_item = (Ewk_Context_Menu_Item *)data;
  1059. info("Selected context menu item: %s.", ewk_context_menu_item_title_get(ewk_item));
  1060. ewk_context_menu_item_select(ewk_context_menu_item_parent_menu_get(ewk_item), ewk_item);
  1061. ewk_context_menu_hide(ewk_context_menu_item_parent_menu_get(ewk_item));
  1062. }
  1063. static void
  1064. context_menu_populate(Evas_Object* context_menu, Ewk_Context_Menu *ewk_menu, Elm_Object_Item *parent_item)
  1065. {
  1066. if (!context_menu || !ewk_menu) {
  1067. info("ERROR: necessary objects are NULL.");
  1068. return;
  1069. }
  1070. const Eina_List *list = ewk_context_menu_items_get(ewk_menu);
  1071. const Eina_List *l;
  1072. void *data;
  1073. Ewk_Context_Menu_Item *ewk_item;
  1074. Elm_Object_Item *elm_menu_item;
  1075. Evas_Object *elm_check_item;
  1076. EINA_LIST_FOREACH(list, l, data) {
  1077. ewk_item = (Ewk_Context_Menu_Item *)data;
  1078. switch (ewk_context_menu_item_type_get(ewk_item)) {
  1079. case EWK_ACTION_TYPE:
  1080. elm_menu_item = elm_menu_item_add(context_menu, parent_item, NULL, ewk_context_menu_item_title_get(ewk_item), context_menu_item_selected_cb, ewk_item);
  1081. break;
  1082. case EWK_CHECKABLE_ACTION_TYPE:
  1083. elm_check_item = elm_check_add(context_menu);
  1084. elm_menu_item = elm_menu_item_add(context_menu, parent_item, NULL, ewk_context_menu_item_title_get(ewk_item), context_menu_item_selected_cb, ewk_item);
  1085. elm_object_item_content_set(elm_menu_item, elm_check_item);
  1086. elm_check_state_set(elm_check_item, ewk_context_menu_item_checked_get(ewk_item));
  1087. break;
  1088. case EWK_SUBMENU_TYPE:
  1089. elm_menu_item = elm_menu_item_add(context_menu, parent_item, NULL, ewk_context_menu_item_title_get(ewk_item), NULL, ewk_item);
  1090. if (elm_menu_item)
  1091. context_menu_populate(context_menu, ewk_context_menu_item_submenu_get(ewk_item), elm_menu_item);
  1092. break;
  1093. default:
  1094. continue;
  1095. }
  1096. elm_object_item_disabled_set(elm_menu_item, !ewk_context_menu_item_enabled_get(ewk_item));
  1097. }
  1098. }
  1099. static Eina_Bool
  1100. on_context_menu_show(Ewk_View_Smart_Data *sd, Evas_Coord x, Evas_Coord y, Ewk_Context_Menu *menu)
  1101. {
  1102. Browser_Window *window = window_find_with_ewk_view(sd->self);
  1103. if (!window || !menu) {
  1104. info("ERROR: necessary objects are NULL.");
  1105. return EINA_FALSE;
  1106. }
  1107. window->context_menu.elm_menu = elm_menu_add(window->elm_window);
  1108. if (!window->context_menu.elm_menu) {
  1109. info("ERROR: could not create menu widget.");
  1110. return EINA_FALSE;
  1111. }
  1112. window->context_menu.ewk_menu = menu;
  1113. context_menu_populate(window->context_menu.elm_menu, menu, NULL);
  1114. info("Showing context menu at (%d, %d).", x, y);
  1115. elm_menu_move(window->context_menu.elm_menu, x, y);
  1116. evas_object_show(window->context_menu.elm_menu);
  1117. return EINA_TRUE;
  1118. }
  1119. static Eina_Bool
  1120. on_context_menu_hide(Ewk_View_Smart_Data *sd)
  1121. {
  1122. Browser_Window *window = window_find_with_ewk_view(sd->self);
  1123. if (!window || !window->context_menu.elm_menu) {
  1124. info("ERROR: necessary objects are NULL.");
  1125. return EINA_FALSE;
  1126. }
  1127. elm_menu_close(window->context_menu.elm_menu);
  1128. evas_object_del(window->context_menu.elm_menu);
  1129. window->context_menu.elm_menu = NULL;
  1130. window->context_menu.ewk_menu = NULL;
  1131. return EINA_TRUE;
  1132. }
  1133. static void
  1134. auth_popup_close(Auth_Data *auth_data)
  1135. {
  1136. ewk_object_unref(auth_data->request);
  1137. evas_object_del(auth_data->popup);
  1138. free(auth_data);
  1139. }
  1140. static void
  1141. on_auth_cancel(void *user_data, Evas_Object *obj, void *event_info)
  1142. {
  1143. Auth_Data *auth_data = (Auth_Data *)user_data;
  1144. ewk_auth_request_cancel(auth_data->request);
  1145. auth_popup_close(auth_data);
  1146. }
  1147. static void
  1148. on_auth_ok(void *user_data, Evas_Object *obj, void *event_info)
  1149. {
  1150. Auth_Data *auth_data = (Auth_Data *)user_data;
  1151. const char *username = elm_entry_entry_get(auth_data->username_entry);
  1152. const char *password = elm_entry_entry_get(auth_data->password_entry);
  1153. ewk_auth_request_authenticate(auth_data->request, username, password);
  1154. auth_popup_close(auth_data);
  1155. }
  1156. static void
  1157. on_authentication_request(void *user_data, Evas_Object *obj, void *event_info)
  1158. {
  1159. Browser_Window *window = (Browser_Window *)user_data;
  1160. Ewk_Auth_Request *request = ewk_object_ref((Ewk_Auth_Request *)event_info);
  1161. Auth_Data *auth_data = (Auth_Data *)malloc(sizeof(Auth_Data));
  1162. auth_data->request = request;
  1163. Evas_Object *auth_popup = elm_popup_add(window->elm_window);
  1164. auth_data->popup = auth_popup;
  1165. evas_object_size_hint_weight_set(auth_popup, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
  1166. elm_object_part_text_set(auth_popup, "title,text", "Authentication Required");
  1167. /* Popup Content */
  1168. Evas_Object *vbox = elm_box_add(auth_popup);
  1169. elm_box_padding_set(vbox, 0, 4);
  1170. evas_object_size_hint_weight_set(vbox, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
  1171. evas_object_size_hint_align_set(vbox, EVAS_HINT_FILL, EVAS_HINT_FILL);
  1172. elm_object_content_set(auth_popup, vbox);
  1173. evas_object_show(vbox);
  1174. /* Authentication message */
  1175. Evas_Object *label = elm_label_add(auth_popup);
  1176. elm_label_line_wrap_set(label, ELM_WRAP_WORD);
  1177. Eina_Strbuf *auth_text = eina_strbuf_new();
  1178. const char *host = ewk_auth_request_host_get(request);
  1179. const char *realm = ewk_auth_request_realm_get(request);
  1180. eina_strbuf_append_printf(auth_text, "A username and password are being requested by %s. The site says: \"%s\"", host, realm ? realm : "");
  1181. elm_object_text_set(label, eina_strbuf_string_get(auth_text));
  1182. eina_strbuf_free(auth_text);
  1183. evas_object_size_hint_weight_set(label, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
  1184. evas_object_size_hint_align_set(label, EVAS_HINT_FILL, EVAS_HINT_FILL);
  1185. elm_box_pack_end(vbox, label);
  1186. evas_object_show(label);
  1187. /* Credential table */
  1188. Evas_Object *table = elm_table_add(auth_popup);
  1189. elm_table_padding_set(table, 2, 2);
  1190. elm_table_homogeneous_set(table, EINA_TRUE);
  1191. evas_object_size_hint_weight_set(table, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
  1192. evas_object_size_hint_align_set(table, EVAS_HINT_FILL, EVAS_HINT_FILL);
  1193. elm_box_pack_end(vbox, table);
  1194. evas_object_show(table);
  1195. /* Username row */
  1196. Evas_Object *username_label = elm_label_add(auth_popup);
  1197. elm_object_text_set(username_label, "Username:");
  1198. evas_object_size_hint_weight_set(username_label, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
  1199. evas_object_size_hint_align_set(username_label, 1, EVAS_HINT_FILL);
  1200. elm_table_pack(table, username_label, 0, 0, 1, 1);
  1201. evas_object_show(username_label);
  1202. Evas_Object *username_entry = elm_entry_add(auth_popup);
  1203. auth_data->username_entry = username_entry;
  1204. elm_entry_scrollable_set(username_entry, EINA_TRUE);
  1205. elm_entry_single_line_set(username_entry, EINA_TRUE);
  1206. elm_entry_text_style_user_push(username_entry, "DEFAULT='font_size=18'");
  1207. const char *suggested_username = ewk_auth_request_suggested_username_get(request);
  1208. elm_entry_entry_set(username_entry, suggested_username ? suggested_username : "");
  1209. evas_object_size_hint_weight_set(username_entry, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
  1210. evas_object_size_hint_align_set(username_entry, EVAS_HINT_FILL, EVAS_HINT_FILL);
  1211. elm_table_pack(table, username_entry, 1, 0, 2, 1);
  1212. elm_object_focus_set(username_entry, EINA_TRUE);
  1213. evas_object_show(username_entry);
  1214. /* Password row */
  1215. Evas_Object *password_label = elm_label_add(auth_popup);
  1216. elm_object_text_set(password_label, "Password:");
  1217. evas_object_size_hint_weight_set(password_label, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
  1218. evas_object_size_hint_align_set(password_label, 1, EVAS_HINT_FILL);
  1219. elm_table_pack(table, password_label, 0, 1, 1, 1);
  1220. evas_object_show(password_label);
  1221. Evas_Object *password_entry = elm_entry_add(auth_popup);
  1222. auth_data->password_entry = password_entry;
  1223. elm_entry_scrollable_set(password_entry, EINA_TRUE);
  1224. elm_entry_single_line_set(password_entry, EINA_TRUE);
  1225. elm_entry_password_set(password_entry, EINA_TRUE);
  1226. elm_entry_text_style_user_push(password_entry, "DEFAULT='font_size=18'");
  1227. evas_object_size_hint_weight_set(password_entry, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
  1228. evas_object_size_hint_align_set(password_entry, EVAS_HINT_FILL, EVAS_HINT_FILL);
  1229. elm_table_pack(table, password_entry, 1, 1, 2, 1);
  1230. evas_object_show(password_entry);
  1231. /* Popup buttons */
  1232. Evas_Object *cancel_button = elm_button_add(auth_popup);
  1233. elm_object_text_set(cancel_button, "Cancel");
  1234. elm_object_part_content_set(auth_popup, "button1", cancel_button);
  1235. evas_object_smart_callback_add(cancel_button, "clicked", on_auth_cancel, auth_data);
  1236. Evas_Object *ok_button = elm_button_add(auth_popup);
  1237. elm_object_text_set(ok_button, "OK");
  1238. elm_object_part_content_set(auth_popup, "button2", ok_button);
  1239. evas_object_smart_callback_add(ok_button, "clicked", on_auth_ok, auth_data);
  1240. evas_object_show(auth_popup);
  1241. }
  1242. static void
  1243. on_tooltip_text_set(void *user_data, Evas_Object *obj, void *event_info)
  1244. {
  1245. Browser_Window *window = (Browser_Window *)user_data;
  1246. const char *message = (const char*)event_info;
  1247. elm_object_tooltip_text_set(window->elm_window, message);
  1248. window->tooltip.text_set = EINA_TRUE;
  1249. window_tooltip_update(window);
  1250. }
  1251. static void
  1252. on_tooltip_text_unset(void *user_data, Evas_Object *obj, void *event_info)
  1253. {
  1254. Browser_Window *window = (Browser_Window *)user_data;
  1255. window_tooltip_hide(window);
  1256. elm_object_tooltip_unset(window->elm_window);
  1257. window->tooltip.text_set = EINA_FALSE;
  1258. }
  1259. static void
  1260. on_home_button_clicked(void *user_data, Evas_Object *home_button, void *event_info)
  1261. {
  1262. Browser_Window *window = (Browser_Window *)user_data;
  1263. ewk_view_url_set(window->ewk_view, DEFAULT_URL);
  1264. }
  1265. static void
  1266. on_window_deletion(void *user_data, Evas_Object *elm_window, void *event_info)
  1267. {
  1268. window_close(window_find_with_elm_window(elm_window));
  1269. }
  1270. static Evas_Object *
  1271. create_toolbar_button(Evas_Object *elm_window, const char *icon_name)
  1272. {
  1273. Evas_Object *button = elm_button_add(elm_window);
  1274. Evas_Object *icon = elm_icon_add(elm_window);
  1275. elm_icon_standard_set(icon, icon_name);
  1276. evas_object_size_hint_max_set(icon, TOOL_BAR_ICON_SIZE, TOOL_BAR_ICON_SIZE);
  1277. evas_object_color_set(icon, 44, 44, 102, 128);
  1278. evas_object_show(icon);
  1279. elm_object_part_content_set(button, "icon", icon);
  1280. evas_object_size_hint_min_set(button, TOOL_BAR_BUTTON_SIZE, TOOL_BAR_BUTTON_SIZE);
  1281. return button;
  1282. }
  1283. static Browser_Window *window_create(Evas_Object *opener, const char *url, int width, int height, Eina_Bool view_mode)
  1284. {
  1285. Browser_Window *window = calloc(1, sizeof(Browser_Window));
  1286. if (!window) {
  1287. info("ERROR: could not create browser window.");
  1288. return NULL;
  1289. }
  1290. /* Initialize tooltip information */
  1291. window->tooltip.show_timer = NULL;
  1292. window->tooltip.activated = EINA_FALSE;
  1293. window->tooltip.text_set = EINA_FALSE;
  1294. window->tooltip.shown = EINA_FALSE;
  1295. /* Create window */
  1296. window->elm_window = elm_win_add(NULL, "minibrowser-window", ELM_WIN_BASIC);
  1297. elm_win_title_set(window->elm_window, APP_NAME);
  1298. evas_object_smart_callback_add(window->elm_window, "delete,request", on_window_deletion, &window);
  1299. /* Create window background */
  1300. Evas_Object *bg = elm_bg_add(window->elm_window);
  1301. elm_bg_color_set(bg, 193, 192, 191);
  1302. evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
  1303. elm_win_resize_object_add(window->elm_window, bg);
  1304. evas_object_show(bg);
  1305. /* Create vertical layout */
  1306. Evas_Object *vertical_layout = elm_box_add(window->elm_window);
  1307. elm_box_padding_set(vertical_layout, 0, 2);
  1308. evas_object_size_hint_weight_set(vertical_layout, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
  1309. elm_win_resize_object_add(window->elm_window, vertical_layout);
  1310. evas_object_show(vertical_layout);
  1311. /* Create horizontal layout for top bar */
  1312. Evas_Object *horizontal_layout = elm_box_add(window->elm_window);
  1313. elm_box_horizontal_set(horizontal_layout, EINA_TRUE);
  1314. evas_object_size_hint_weight_set(horizontal_layout, EVAS_HINT_EXPAND, 0.0);
  1315. evas_object_size_hint_align_set(horizontal_layout, EVAS_HINT_FILL, 0.0);
  1316. elm_box_pack_end(vertical_layout, horizontal_layout);
  1317. evas_object_show(horizontal_layout);
  1318. /* Create Back button */
  1319. window->back_button = create_toolbar_button(window->elm_window, "arrow_left");
  1320. evas_object_smart_callback_add(window->back_button, "clicked", on_back_button_clicked, window);
  1321. elm_object_disabled_set(window->back_button, EINA_TRUE);
  1322. evas_object_size_hint_weight_set(window->back_button, 0.0, EVAS_HINT_EXPAND);
  1323. evas_object_size_hint_align_set(window->back_button, 0.0, 0.5);
  1324. elm_box_pack_end(horizontal_layout, window->back_button);
  1325. evas_object_show(window->back_button);
  1326. /* Create Forward button */
  1327. window->forward_button = create_toolbar_button(window->elm_window, "arrow_right");
  1328. evas_object_smart_callback_add(window->forward_button, "clicked", on_forward_button_clicked, window);
  1329. elm_object_disabled_set(window->forward_button, EINA_TRUE);
  1330. evas_object_size_hint_weight_set(window->forward_button, 0.0, EVAS_HINT_EXPAND);
  1331. evas_object_size_hint_align_set(window->forward_button, 0.0, 0.5);
  1332. elm_box_pack_end(horizontal_layout, window->forward_button);
  1333. evas_object_show(window->forward_button);
  1334. /* Create URL bar */
  1335. window->url_bar = elm_entry_add(window->elm_window);
  1336. elm_entry_scrollable_set(window->url_bar, EINA_TRUE);
  1337. elm_entry_scrollbar_policy_set(window->url_bar, ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_OFF);
  1338. elm_entry_single_line_set(window->url_bar, EINA_TRUE);
  1339. elm_entry_cnp_mode_set(window->url_bar, ELM_CNP_MODE_PLAINTEXT);
  1340. elm_entry_text_style_user_push(window->url_bar, "DEFAULT='font_size=18'");
  1341. evas_object_smart_callback_add(window->url_bar, "activated", on_url_bar_activated, window);
  1342. evas_object_smart_callback_add(window->url_bar, "clicked", on_url_bar_clicked, window);
  1343. evas_object_size_hint_weight_set(window->url_bar, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
  1344. evas_object_size_hint_align_set(window->url_bar, EVAS_HINT_FILL, EVAS_HINT_FILL);
  1345. elm_box_pack_end(horizontal_layout, window->url_bar);
  1346. evas_object_show(window->url_bar);
  1347. /* Create Refresh button */
  1348. Evas_Object *refresh_button = create_toolbar_button(window->elm_window, "refresh");
  1349. evas_object_smart_callback_add(refresh_button, "clicked", on_refresh_button_clicked, window);
  1350. evas_object_size_hint_weight_set(refresh_button, 0.0, EVAS_HINT_EXPAND);
  1351. evas_object_size_hint_align_set(refresh_button, 1.0, 0.5);
  1352. elm_box_pack_end(horizontal_layout, refresh_button);
  1353. evas_object_show(refresh_button);
  1354. /* Create Home button */
  1355. Evas_Object *home_button = create_toolbar_button(window->elm_window, "home");
  1356. evas_object_smart_callback_add(home_button, "clicked", on_home_button_clicked, window);
  1357. evas_object_size_hint_weight_set(home_button, 0.0, EVAS_HINT_EXPAND);
  1358. evas_object_size_hint_align_set(home_button, 1.0, 0.5);
  1359. elm_box_pack_end(horizontal_layout, home_button);
  1360. evas_object_show(home_button);
  1361. /* Create Search bar */
  1362. window->search.search_bar = elm_box_add(window->elm_window);
  1363. elm_box_horizontal_set(window->search.search_bar, EINA_TRUE);
  1364. evas_object_size_hint_min_set(window->search.search_bar, SEARCH_FIELD_SIZE + 2 * SEARCH_BUTTON_SIZE, 0);
  1365. evas_object_size_hint_align_set(window->search.search_bar, 0.0, EVAS_HINT_FILL);
  1366. elm_box_pack_end(vertical_layout, window->search.search_bar);
  1367. /* Create Search field */
  1368. window->search.search_field = elm_entry_add(window->elm_window);
  1369. elm_entry_scrollable_set(window->search.search_field, EINA_TRUE);
  1370. elm_entry_scrollbar_policy_set(window->search.search_field, ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_OFF);
  1371. elm_entry_single_line_set(window->search.search_field, EINA_TRUE);
  1372. elm_entry_cnp_mode_set(window->search.search_field, ELM_CNP_MODE_PLAINTEXT);
  1373. elm_entry_text_style_user_push(window->search.search_field, "DEFAULT='font_size=14'");
  1374. evas_object_smart_callback_add(window->search.search_field, "activated", on_search_field_activated, window);
  1375. evas_object_smart_callback_add(window->search.search_field, "changed", on_search_field_activated, window);
  1376. evas_object_smart_callback_add(window->search.search_field, "aborted", on_search_field_aborted, window);
  1377. evas_object_smart_callback_add(window->search.search_field, "clicked", on_search_field_clicked, window);
  1378. evas_object_size_hint_weight_set(window->search.search_field, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
  1379. evas_object_size_hint_align_set(window->search.search_field, EVAS_HINT_FILL, EVAS_HINT_FILL);
  1380. elm_box_pack_end(window->search.search_bar, window->search.search_field);
  1381. /* Create Search backward button */
  1382. window->search.backward_button = create_toolbar_button(window->elm_window, "arrow_up");
  1383. evas_object_smart_callback_add(window->search.backward_button, "clicked", on_search_backward_button_clicked, window);
  1384. elm_object_disabled_set(window->search.backward_button, EINA_FALSE);
  1385. evas_object_size_hint_weight_set(window->search.backward_button, 0.0, EVAS_HINT_EXPAND);
  1386. evas_object_size_hint_align_set(window->search.backward_button, 1.0, 0.5);
  1387. evas_object_size_hint_min_set(window->search.backward_button, SEARCH_BUTTON_SIZE, SEARCH_BUTTON_SIZE);
  1388. elm_box_pack_end(window->search.search_bar, window->search.backward_button);
  1389. /* Create Search forwardward button */
  1390. window->search.forward_button = create_toolbar_button(window->elm_window, "arrow_down");
  1391. evas_object_smart_callback_add(window->search.forward_button, "clicked", on_search_forward_button_clicked, window);
  1392. elm_object_disabled_set(window->search.forward_button, EINA_FALSE);
  1393. evas_object_size_hint_weight_set(window->search.forward_button, 0.0, EVAS_HINT_EXPAND);
  1394. evas_object_size_hint_align_set(window->search.forward_button, 1.0, 0.5);
  1395. evas_object_size_hint_min_set(window->search.forward_button, SEARCH_BUTTON_SIZE, SEARCH_BUTTON_SIZE);
  1396. elm_box_pack_end(window->search.search_bar, window->search.forward_button);
  1397. /* Create ewk_view */
  1398. Ewk_View_Smart_Class *ewkViewClass = miniBrowserViewSmartClass();
  1399. ewkViewClass->run_javascript_alert = on_javascript_alert;
  1400. ewkViewClass->run_javascript_confirm = on_javascript_confirm;
  1401. ewkViewClass->run_javascript_prompt = on_javascript_prompt;
  1402. ewkViewClass->window_geometry_get = on_window_geometry_get;
  1403. ewkViewClass->window_geometry_set = on_window_geometry_set;
  1404. ewkViewClass->fullscreen_enter = on_fullscreen_enter;
  1405. ewkViewClass->fullscreen_exit = on_fullscreen_exit;
  1406. ewkViewClass->window_create = on_window_create;
  1407. ewkViewClass->window_close = on_window_close;
  1408. ewkViewClass->popup_menu_show = on_popup_menu_show;
  1409. ewkViewClass->popup_menu_hide = on_popup_menu_hide;
  1410. ewkViewClass->context_menu_show = on_context_menu_show;
  1411. ewkViewClass->context_menu_hide = on_context_menu_hide;
  1412. ewkViewClass->input_picker_color_request = on_color_picker_request;
  1413. ewkViewClass->input_picker_color_dismiss = on_color_picker_dismiss;
  1414. Evas *evas = evas_object_evas_get(window->elm_window);
  1415. if (legacy_behavior_enabled) {
  1416. // Use raw WK2 api to create a view using legacy mode.
  1417. window->ewk_view = (Evas_Object*)WKViewCreate(evas, 0, 0);
  1418. } else {
  1419. Evas_Smart *smart = evas_smart_class_new(&ewkViewClass->sc);
  1420. Ewk_Context *context = opener ? ewk_view_context_get(opener) : ewk_context_default_get();
  1421. Ewk_Page_Group *pageGroup = opener ? ewk_view_page_group_get(opener) : ewk_page_group_create("");
  1422. window->ewk_view = ewk_view_smart_add(evas, smart, context, pageGroup);
  1423. }
  1424. ewk_view_theme_set(window->ewk_view, TEST_THEME_DIR "/default.edj");
  1425. if (device_pixel_ratio)
  1426. ewk_view_device_pixel_ratio_set(window->ewk_view, (float)device_pixel_ratio);
  1427. ewk_view_source_mode_set(window->ewk_view, view_mode);
  1428. ewk_view_user_agent_set(window->ewk_view, user_agent_string);
  1429. /* Set the zoom level to default */
  1430. window->current_zoom_level = DEFAULT_ZOOM_LEVEL;
  1431. Ewk_Settings *settings = ewk_view_settings_get(window->ewk_view);
  1432. ewk_settings_file_access_from_file_urls_allowed_set(settings, EINA_TRUE);
  1433. ewk_settings_encoding_detector_enabled_set(settings, encoding_detector_enabled);
  1434. ewk_settings_frame_flattening_enabled_set(settings, frame_flattening_enabled);
  1435. ewk_settings_local_storage_enabled_set(settings, local_storage_enabled);
  1436. info("HTML5 local storage is %s for this view.", local_storage_enabled ? "enabled" : "disabled");
  1437. elm_win_fullscreen_set(window->elm_window, fullscreen_enabled);
  1438. ewk_settings_developer_extras_enabled_set(settings, EINA_TRUE);
  1439. ewk_settings_preferred_minimum_contents_width_set(settings, 0);
  1440. ewk_text_checker_continuous_spell_checking_enabled_set(spell_checking_enabled);
  1441. evas_object_smart_callback_add(window->ewk_view, "authentication,request", on_authentication_request, window);
  1442. evas_object_smart_callback_add(window->ewk_view, "download,failed", on_download_failed, window);
  1443. evas_object_smart_callback_add(window->ewk_view, "download,finished", on_download_finished, window);
  1444. evas_object_smart_callback_add(window->ewk_view, "download,request", on_download_request, window);
  1445. evas_object_smart_callback_add(window->ewk_view, "file,chooser,request", on_file_chooser_request, window);
  1446. evas_object_smart_callback_add(window->ewk_view, "favicon,changed", on_view_favicon_changed, window);
  1447. evas_object_smart_callback_add(window->ewk_view, "load,error", on_error, window);
  1448. evas_object_smart_callback_add(window->ewk_view, "load,progress", on_progress, window);
  1449. evas_object_smart_callback_add(window->ewk_view, "title,changed", on_title_changed, window);
  1450. evas_object_smart_callback_add(window->ewk_view, "url,changed", on_url_changed, window);
  1451. evas_object_smart_callback_add(window->ewk_view, "back,forward,list,changed", on_back_forward_list_changed, window);
  1452. evas_object_smart_callback_add(window->ewk_view, "tooltip,text,set", on_tooltip_text_set, window);
  1453. evas_object_smart_callback_add(window->ewk_view, "tooltip,text,unset", on_tooltip_text_unset, window);
  1454. evas_object_event_callback_add(window->ewk_view, EVAS_CALLBACK_KEY_DOWN, on_key_down, window);
  1455. evas_object_event_callback_add(window->ewk_view, EVAS_CALLBACK_MOUSE_DOWN, on_mouse_down, window);
  1456. evas_object_size_hint_weight_set(window->ewk_view, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
  1457. evas_object_size_hint_align_set(window->ewk_view, EVAS_HINT_FILL, EVAS_HINT_FILL);
  1458. elm_box_pack_before(vertical_layout, window->ewk_view, window->search.search_bar);
  1459. evas_object_show(window->ewk_view);
  1460. if (url && strcmp(url, "about:blank")) // Do not reset 'about:blank' as it would erase all previous document modifications.
  1461. ewk_view_url_set(window->ewk_view, url);
  1462. evas_object_resize(window->elm_window, width ? width : window_width, height ? height : window_height);
  1463. evas_object_show(window->elm_window);
  1464. search_box_hide(window);
  1465. view_focus_set(window, EINA_TRUE);
  1466. evas_object_event_callback_add(window->ewk_view, EVAS_CALLBACK_MOUSE_IN, on_mouse_in, window);
  1467. evas_object_event_callback_add(window->ewk_view, EVAS_CALLBACK_MOUSE_OUT, on_mouse_out, window);
  1468. evas_object_event_callback_add(window->ewk_view, EVAS_CALLBACK_MOUSE_MOVE, on_mouse_move, window);
  1469. evas_object_event_callback_add(window->elm_window, EVAS_CALLBACK_RESIZE, on_window_resize, window);
  1470. return window;
  1471. }
  1472. static Ewk_Cookie_Accept_Policy
  1473. parse_cookies_policy(const char *input_string)
  1474. {
  1475. if (!strcmp(input_string, "always"))
  1476. return EWK_COOKIE_ACCEPT_POLICY_ALWAYS;
  1477. if (!strcmp(input_string, "never"))
  1478. return EWK_COOKIE_ACCEPT_POLICY_NEVER;
  1479. if (strcmp(input_string, "no-third-party"))
  1480. info("Unrecognized type for cookies policy: %s.", input_string);
  1481. return EWK_COOKIE_ACCEPT_POLICY_NO_THIRD_PARTY;
  1482. }
  1483. static void
  1484. parse_window_size(const char *input_string, int *width, int *height)
  1485. {
  1486. static const unsigned max_length = 4;
  1487. int parsed_width;
  1488. int parsed_height;
  1489. char **arr;
  1490. unsigned elements;
  1491. arr = eina_str_split_full(input_string, "x", 0, &elements);
  1492. if (elements == 2 && (strlen(arr[0]) <= max_length) && (strlen(arr[1]) <= max_length)) {
  1493. parsed_width = atoi(arr[0]);
  1494. if (width && parsed_width)
  1495. *width = parsed_width;
  1496. parsed_height = atoi(arr[1]);
  1497. if (height && parsed_height)
  1498. *height = parsed_height;
  1499. }
  1500. free(arr[0]);
  1501. free(arr);
  1502. }
  1503. EAPI_MAIN int
  1504. elm_main(int argc, char *argv[])
  1505. {
  1506. int args = 1;
  1507. unsigned char quitOption = 0;
  1508. Browser_Window *window;
  1509. char *window_size_string = NULL;
  1510. char *cookies_policy_string = NULL;
  1511. Ecore_Getopt_Value values[] = {
  1512. ECORE_GETOPT_VALUE_STR(evas_engine_name),
  1513. ECORE_GETOPT_VALUE_STR(window_size_string),
  1514. ECORE_GETOPT_VALUE_STR(user_agent_string),
  1515. ECORE_GETOPT_VALUE_BOOL(legacy_behavior_enabled),
  1516. ECORE_GETOPT_VALUE_DOUBLE(device_pixel_ratio),
  1517. ECORE_GETOPT_VALUE_BOOL(quitOption),
  1518. ECORE_GETOPT_VALUE_BOOL(encoding_detector_enabled),
  1519. ECORE_GETOPT_VALUE_BOOL(frame_flattening_enabled),
  1520. ECORE_GETOPT_VALUE_BOOL(local_storage_enabled),
  1521. ECORE_GETOPT_VALUE_BOOL(fullscreen_enabled),
  1522. ECORE_GETOPT_VALUE_BOOL(spell_checking_enabled),
  1523. ECORE_GETOPT_VALUE_STR(cookies_policy_string),
  1524. ECORE_GETOPT_VALUE_BOOL(quitOption),
  1525. ECORE_GETOPT_VALUE_BOOL(quitOption),
  1526. ECORE_GETOPT_VALUE_BOOL(quitOption),
  1527. ECORE_GETOPT_VALUE_NONE
  1528. };
  1529. if (!ewk_init())
  1530. return EXIT_FAILURE;
  1531. ewk_view_smart_class_set(miniBrowserViewSmartClass());
  1532. ecore_app_args_set(argc, (const char **) argv);
  1533. args = ecore_getopt_parse(&options, values, argc, argv);
  1534. if (args < 0)
  1535. return quit(EINA_FALSE, "ERROR: could not parse options.\n");
  1536. if (quitOption)
  1537. return quit(EINA_TRUE, NULL);
  1538. if (evas_engine_name)
  1539. elm_config_preferred_engine_set(evas_engine_name);
  1540. #if defined(WTF_USE_ACCELERATED_COMPOSITING) && defined(HAVE_ECORE_X)
  1541. else {
  1542. evas_engine_name = "opengl_x11";
  1543. elm_config_preferred_engine_set(evas_engine_name);
  1544. }
  1545. #endif
  1546. // Enable favicon database.
  1547. Ewk_Context *context = ewk_context_default_get();
  1548. ewk_context_favicon_database_directory_set(context, NULL);
  1549. if (cookies_policy_string)
  1550. ewk_cookie_manager_accept_policy_set(ewk_context_cookie_manager_get(context), parse_cookies_policy(cookies_policy_string));
  1551. if (window_size_string)
  1552. parse_window_size(window_size_string, &window_width, &window_height);
  1553. if (args < argc) {
  1554. char *url = url_from_user_input(argv[args]);
  1555. window = window_create(NULL, url, 0, 0, EINA_FALSE);
  1556. free(url);
  1557. } else
  1558. window = window_create(NULL, DEFAULT_URL, 0, 0, EINA_FALSE);
  1559. if (!window)
  1560. return quit(EINA_FALSE, "ERROR: could not create browser window.\n");
  1561. windows = eina_list_append(windows, window);
  1562. elm_run();
  1563. return quit(EINA_TRUE, NULL);
  1564. }
  1565. ELM_MAIN()