Web\+Kit-\/\+E\+F\+L is independent of any particular toolkit, such as Elementary, so using it on applications requires that the programmer writes a lot of boiler plate code to manage to manage the web object.

For a full featured browser this may make sense, as the programmer will want to have full control of every aspect of the web object, since it\textquotesingle{}s the main component of the application. But other programs with simpler requirements, having to write so much code is undesired.

This is where elm\+\_\+web comes in. Its purpose is to provide a simple way for developers to embed a simple web object in their programs, simplifying the common use cases.

This is not to say that a browser can\textquotesingle{}t be made out of it, as this example shows.

We\textquotesingle{}ll be making a simple browser, consisting of one window with an U\+R\+L bar, a toolbar to be used for the tabs and a pager to show one page at a time.

When all tabs are closed, we\textquotesingle{}ll be showing a default view with some custom content, for which we need to get the internal {\ttfamily ewk\+\_\+view} object and use some Web\+Kit functions on it, thus we need to include the necessary headers first.

 
\begin{DoxyCodeInclude}
\textcolor{preprocessor}{#include <Elementary.h>}
\textcolor{preprocessor}{#ifdef HAVE\_ELEMENTARY\_WEB}
\textcolor{preprocessor}{#include <EWebKit.h>}

\end{DoxyCodeInclude}


A struct to keep track of the different widgets in use and the currently shown tab. There\textquotesingle{}s also an {\ttfamily exiting} flag, used to work around the overly simplistic way in which this example is written, just to avoid some warnings when closing the program.


\begin{DoxyCodeInclude}
\textcolor{keyword}{typedef} \textcolor{keyword}{struct }\_Tab\_Data Tab\_Data;

\textcolor{keyword}{typedef} \textcolor{keyword}{struct}
\{
   Evas\_Object *win;
   Evas\_Object *main\_box;
   Evas\_Object *naviframe;
   Evas\_Object *url\_entry;
   Evas\_Object *default\_web;
   Evas\_Object *tabs;
   Evas\_Object *close\_tab;
   Evas\_Object *search\_box;
   Evas\_Object *search\_entry;

   \textcolor{keyword}{struct }\{
        Evas\_Object *back;
        Evas\_Object *fwd;
        Evas\_Object *refresh;
   \} nav;

   Tab\_Data *current\_tab;

   Eina\_Bool exiting : 1;
\} App\_Data;

\end{DoxyCodeInclude}


Each tab has its own struct too, but there\textquotesingle{}s not much to it. 
\begin{DoxyCodeInclude}

\textcolor{keyword}{struct }\_Tab\_Data
\{
   Evas\_Object *web;
   App\_Data *app;
   Elm_Object_Item *tab;
\};

\end{DoxyCodeInclude}


Whenever the currently selected tab changes, we need to update some state on the application. The back and forward buttons need to be disabled accordingly and the U\+R\+L bar needs to show the right address.


\begin{DoxyCodeInclude}
\textcolor{keyword}{static} \textcolor{keywordtype}{void}
nav\_button\_update(App\_Data *ad)
\{
   Eina\_Bool back, fwd;

   back = !elm\_web\_back\_possible\_get(ad->current\_tab->web);
   fwd = !elm\_web\_forward\_possible\_get(ad->current\_tab->web);

   elm_object_disabled_set(ad->nav.back, back);
   elm_object_disabled_set(ad->nav.fwd, fwd);
\}

\textcolor{keyword}{static} \textcolor{keywordtype}{void}
tab\_current\_set(Tab\_Data *td)
\{
   \textcolor{keyword}{const} \textcolor{keywordtype}{char} *url;

   \textcolor{keywordflow}{if} (td == td->app->current\_tab)
     \textcolor{keywordflow}{return};

   td->app->current\_tab = td;

   url = elm\_web\_url\_get(td->web);
   elm\_object\_text\_set(td->app->url\_entry, url);

   nav\_button\_update(td->app);
   elm\_entry\_icon\_visible\_set(td->app->url\_entry, EINA\_TRUE);

   elm\_naviframe\_item\_simple\_promote(td->app->naviframe, td->web);
\}

\end{DoxyCodeInclude}


Other updates happen based on events from the web object, like title change to update the name shown in the tab, and U\+R\+L change which will update the U\+R\+L bar if the event came from the currently selected tab.


\begin{DoxyCodeInclude}
\textcolor{keyword}{static} \textcolor{keywordtype}{void}
\_title\_changed\_cb(\textcolor{keywordtype}{void} *data, Evas\_Object *obj, \textcolor{keywordtype}{void} *event\_info)
\{
   Tab\_Data *td = data;
   \textcolor{keyword}{const} \textcolor{keywordtype}{char} *title = event\_info;
   \textcolor{keywordtype}{char} buf[20] = \textcolor{stringliteral}{""};

   \textcolor{keywordflow}{if} (title)
     strncpy(buf, title, \textcolor{keyword}{sizeof}(buf) - 1);
   elm_object_item_text_set(td->tab, buf);
\}

\textcolor{keyword}{static} \textcolor{keywordtype}{void}
\_url\_changed\_cb(\textcolor{keywordtype}{void} *data, Evas\_Object *obj, \textcolor{keywordtype}{void} *event\_info)
\{
   Tab\_Data *td = data;
   \textcolor{keyword}{const} \textcolor{keywordtype}{char} *url = event\_info;

   \textcolor{keywordflow}{if} (td != td->app->current\_tab)
     \textcolor{keywordflow}{return};

   nav\_button\_update(td->app);
   elm\_object\_text\_set(td->app->url\_entry, url);
\}

\end{DoxyCodeInclude}


Adding a new tab is just a matter of creating a new web widget, its data and pushing it into the pager. A lot of the things that we should handle here, such as how to react to popups and Java\+Script dialogs, are done already in the {\ttfamily elm\+\_\+web} widget, so we can rely on their default implementations. For the Java\+Script dialogs we are going to avoid having them open in a new window by setting the {\ttfamily Inwin} mode.

There is no default implementation, however, for the requests to create a new window, so we have to handle them by setting a callback function that will ultimately call this very same function to add a new tab.


\begin{DoxyCodeInclude}
Tab\_Data *
tab\_add(App\_Data *ad)
\{
   Tab\_Data *td;

   td = calloc(1, \textcolor{keyword}{sizeof}(Tab\_Data));
   \textcolor{keywordflow}{if} (!td) \textcolor{keywordflow}{return} NULL;

   td->web = elm_web_add(ad->win);
   elm\_web\_window\_create\_hook\_set(td->web, \_web\_create\_window\_cb, ad);
   elm\_web\_inwin\_mode\_set(td->web, EINA\_TRUE);
   evas\_object\_size\_hint\_weight\_set(td->web, EVAS\_HINT\_EXPAND,
                                    EVAS\_HINT\_EXPAND);
   evas\_object\_size\_hint\_align\_set(td->web, EVAS\_HINT\_FILL, EVAS\_HINT\_FILL);
   elm\_naviframe\_item\_simple\_push(ad->naviframe, td->web);

   td->app = ad;
   td->tab = elm\_toolbar\_item\_append(td->app->tabs, NULL, \textcolor{stringliteral}{"New tab"},
                                     \_tab\_clicked\_cb, td);
   elm\_object\_item\_del\_cb\_set(td->tab, \_tb\_item\_del\_cb);

   evas\_object\_data\_set(td->web, \textcolor{stringliteral}{"tab\_data"}, td);

   evas\_object\_smart\_callback\_add(td->web, \textcolor{stringliteral}{"title,changed"}, \_title\_changed\_cb,
                                  td);
   evas\_object\_smart\_callback\_add(td->web, \textcolor{stringliteral}{"url,changed"}, \_url\_changed\_cb, td);
   evas\_object\_event\_callback\_add(td->web, EVAS\_CALLBACK\_FREE, \_web\_free\_cb,
                                  td);

   elm\_toolbar\_item\_selected\_set(td->tab, EINA\_TRUE);
   \textcolor{keywordflow}{return} td;
\}

\end{DoxyCodeInclude}


Entering an address in the U\+R\+L bar will check if a tab exists, and if not, create one and set the U\+R\+L for it. The address needs to conform to the U\+R\+I format, so we check that it does and add the protocol if it\textquotesingle{}s missing.


\begin{DoxyCodeInclude}
\textcolor{keyword}{static} \textcolor{keywordtype}{char} *
url\_sanitize(\textcolor{keyword}{const} \textcolor{keywordtype}{char} *url)
\{
   \textcolor{keywordtype}{char} *fixed\_url;
   \textcolor{keywordtype}{char} *schema;
   \textcolor{keywordtype}{char} *tmp;

   \textcolor{keywordflow}{if} (!url || !*url) \textcolor{keywordflow}{return} NULL;

   tmp = strstr(url, \textcolor{stringliteral}{"://"});
   \textcolor{keywordflow}{if} (!tmp || (tmp == url) || (tmp > (url + 15)))
     \{
        \textcolor{keywordtype}{char} *new\_url = NULL;
        \textcolor{keywordflow}{if} (ecore\_file\_exists(url))
          \{
             schema = \textcolor{stringliteral}{"file"};
             new\_url = ecore\_file\_realpath(url);
          \}
        \textcolor{keywordflow}{else}
          schema = \textcolor{stringliteral}{"http"};

        \textcolor{keywordflow}{if} (asprintf(&fixed\_url, \textcolor{stringliteral}{"%s://%s"}, schema, new\_url ? new\_url : url) >
            0)
          \{
             free(new\_url);
             \textcolor{keywordflow}{return} fixed\_url;
          \}
        free(new\_url);
     \}
   \textcolor{keywordflow}{else}
     \textcolor{keywordflow}{return} strdup(url);

   \textcolor{keywordflow}{return} NULL;
\}

\textcolor{keyword}{static} \textcolor{keywordtype}{void}
tab\_url\_set(Tab\_Data *td, \textcolor{keyword}{const} \textcolor{keywordtype}{char} *url)
\{
   \textcolor{keywordtype}{char} *sane\_url = url\_sanitize(url);
   elm\_web\_url\_set(td->web, sane\_url);
   free(sane\_url);
\}

\textcolor{keyword}{static} \textcolor{keywordtype}{void}
\_url\_entry\_activated\_cb(\textcolor{keywordtype}{void} *data, Evas\_Object *obj, \textcolor{keywordtype}{void} *event\_info)
\{
   App\_Data *ad = data;
   Tab\_Data *td;
   \textcolor{keyword}{const} \textcolor{keywordtype}{char} *url = eina\_stringshare\_ref(elm\_object\_text\_get(obj));

   \textcolor{keywordflow}{if} (!ad->current\_tab)
     td = tab\_add(ad);
   \textcolor{keywordflow}{else}
     td = ad->current\_tab;
   tab\_url\_set(td, url);
   eina\_stringshare\_del(url);
\}

\end{DoxyCodeInclude}


The navigation buttons are simple enough. As for the refresh, it normally reloads the page using anything that may exist in the caches if applicable, but we can press it while holding the {\ttfamily Shift} key to avoid the cache.


\begin{DoxyCodeInclude}
\textcolor{keyword}{static} \textcolor{keywordtype}{void}
\_nav\_back\_cb(\textcolor{keywordtype}{void} *data, Evas\_Object *obj, \textcolor{keywordtype}{void} *event\_info)
\{
   App\_Data *ad = data;

   elm\_web\_back(ad->current\_tab->web);
\}

\textcolor{keyword}{static} \textcolor{keywordtype}{void}
\_nav\_refresh\_cb(\textcolor{keywordtype}{void} *data, Evas\_Object *obj, \textcolor{keywordtype}{void} *event\_info)
\{
   App\_Data *ad = data;
   \textcolor{keyword}{const} Evas\_Modifier *mods = evas\_key\_modifier\_get(evas\_object\_evas\_get(obj));

   \textcolor{keywordflow}{if} (evas\_key\_modifier\_is\_set(mods, \textcolor{stringliteral}{"Shift"}))
     elm\_web\_reload\_full(ad->current\_tab->web);
   \textcolor{keywordflow}{else}
     elm\_web\_reload(ad->current\_tab->web);
\}

\textcolor{keyword}{static} \textcolor{keywordtype}{void}
\_nav\_fwd\_cb(\textcolor{keywordtype}{void} *data, Evas\_Object *obj, \textcolor{keywordtype}{void} *event\_info)
\{
   App\_Data *ad = data;

   elm\_web\_forward(ad->current\_tab->web);
\}

\end{DoxyCodeInclude}


The callback set for the new window request creates a new tab and returns the web widget associated with it. This is important, this function must return a valid web widget returned by \hyperlink{group__Web_ga2429d45ce9bea9428997a1fc3236b66a}{elm\+\_\+web\+\_\+add()}.


\begin{DoxyCodeInclude}
\textcolor{keyword}{static} Evas\_Object *
\_web\_create\_window\_cb(\textcolor{keywordtype}{void} *data, Evas\_Object *obj, Eina\_Bool js, \textcolor{keyword}{const} 
      Elm_Web_Window_Features *wf)
\{
   App\_Data *ad = data;
   Tab\_Data *td;

   td = tab\_add(ad);
   \textcolor{keywordflow}{return} td->web;
\}

\end{DoxyCodeInclude}


Pressing {\ttfamily Ctrl-\/\+F} will bring up the search box. Nothing about the box itself is worth mentioning here, but it works as you would expect from any other browser. While typing on it, it will highlight all occurrences of the searched word. Pressing {\ttfamily Enter} will go to the next instance and the two buttons next to the entry will move forward and backwards through the found keywords.


\begin{DoxyCodeInclude}
\textcolor{keyword}{static} \textcolor{keywordtype}{void}
\_win\_free\_cb(\textcolor{keywordtype}{void} *data, Evas *e, Evas\_Object *obj, \textcolor{keywordtype}{void} *event\_info)
\{
   free(data);
\}

\textcolor{keyword}{static} \textcolor{keywordtype}{void}
\_search\_entry\_changed\_cb(\textcolor{keywordtype}{void} *data, Evas\_Object *obj, \textcolor{keywordtype}{void} *event\_info)
\{
   App\_Data *ad = data;
   \textcolor{keyword}{const} \textcolor{keywordtype}{char} *text;

   text = elm\_object\_text\_get(obj);
   elm\_web\_text\_search(ad->current\_tab->web, text, EINA\_FALSE, EINA\_TRUE,
                       EINA\_TRUE);
   elm\_web\_text\_matches\_unmark\_all(ad->current\_tab->web);
   elm\_web\_text\_matches\_mark(ad->current\_tab->web, text, EINA\_FALSE, EINA\_TRUE,
                             0);
\}

\textcolor{keyword}{static} \textcolor{keywordtype}{void}
\_search\_entry\_activate\_cb(\textcolor{keywordtype}{void} *data, Evas\_Object *obj, \textcolor{keywordtype}{void} *event\_info)
\{
   App\_Data *ad = data;
   \textcolor{keyword}{const} \textcolor{keywordtype}{char} *text;

   text = elm\_object\_text\_get(obj);
   elm\_web\_text\_search(ad->current\_tab->web, text, EINA\_FALSE, EINA\_TRUE,
                       EINA\_TRUE);
\}

\textcolor{keyword}{static} \textcolor{keywordtype}{void}
\_search\_next\_cb(\textcolor{keywordtype}{void} *data, Evas\_Object *obj, \textcolor{keywordtype}{void} *event\_info)
\{
   App\_Data *ad = data;
   \textcolor{keyword}{const} \textcolor{keywordtype}{char} *text;

   text = elm\_object\_text\_get(ad->search\_entry);
   elm\_web\_text\_search(ad->current\_tab->web, text, EINA\_FALSE, EINA\_TRUE,
                       EINA\_TRUE);
\}

\textcolor{keyword}{static} \textcolor{keywordtype}{void}
\_search\_prev\_cb(\textcolor{keywordtype}{void} *data, Evas\_Object *obj, \textcolor{keywordtype}{void} *event\_info)
\{
   App\_Data *ad = data;
   \textcolor{keyword}{const} \textcolor{keywordtype}{char} *text;

   text = elm\_object\_text\_get(ad->search\_entry);
   elm\_web\_text\_search(ad->current\_tab->web, text, EINA\_FALSE, EINA\_FALSE,
                       EINA\_TRUE);
\}

\textcolor{keyword}{static} \textcolor{keywordtype}{void}
\_search\_close\_cb(\textcolor{keywordtype}{void} *data, Evas\_Object *obj, \textcolor{keywordtype}{void} *event\_info)
\{
   App\_Data *ad = data;
   evas\_object\_del(ad->search\_box);
\}

\textcolor{keyword}{static} \textcolor{keywordtype}{void}
\_search\_box\_del\_cb(\textcolor{keywordtype}{void} *data, Evas *e, Evas\_Object *obj, \textcolor{keywordtype}{void} *event\_info)
\{
   App\_Data *ad = data;
   ad->search\_box = NULL;
   ad->search\_entry = NULL;
\}

\textcolor{keyword}{static} \textcolor{keywordtype}{void}
\_win\_search\_trigger\_cb(\textcolor{keywordtype}{void} *data, Evas *e, Evas\_Object *obj, \textcolor{keywordtype}{void} *event\_info)
\{
   Evas\_Event\_Key\_Down *ev = event\_info;
   App\_Data *ad = data;
   Evas\_Object *box, *box2, *entry, *btn, *ic;

   \textcolor{keywordflow}{if} (strcmp(ev->keyname, \textcolor{stringliteral}{"f"}) ||
       !evas\_key\_modifier\_is\_set(ev->modifiers, \textcolor{stringliteral}{"Control"}))
     \textcolor{keywordflow}{return};
   \textcolor{keywordflow}{if} (ad->search\_box || !ad->current\_tab)
     \textcolor{keywordflow}{return};

   box = elm_box_add(ad->win);
   elm\_box\_horizontal\_set(box, EINA\_TRUE);
   evas\_object\_size\_hint\_weight\_set(box, EVAS\_HINT\_EXPAND, 0.0);
   evas\_object\_size\_hint\_align\_set(box, EVAS\_HINT\_FILL, EVAS\_HINT\_FILL);
   elm\_box\_pack\_after(ad->main\_box, box, ad->url\_entry);
   evas\_object\_show(box);

   evas\_object\_event\_callback\_add(box, EVAS\_CALLBACK\_DEL, \_search\_box\_del\_cb,
                                  ad);

   entry = elm_entry_add(ad->win);
   elm\_entry\_single\_line\_set(entry, EINA\_TRUE);
   elm\_entry\_scrollable\_set(entry, EINA\_TRUE);
   evas\_object\_size\_hint\_weight\_set(entry, EVAS\_HINT\_EXPAND, EVAS\_HINT\_EXPAND);
   evas\_object\_size\_hint\_align\_set(entry, EVAS\_HINT\_FILL, EVAS\_HINT\_FILL);
   elm\_box\_pack\_end(box, entry);
   evas\_object\_show(entry);

   evas\_object\_smart\_callback\_add(entry, \textcolor{stringliteral}{"changed"}, \_search\_entry\_changed\_cb,
                                  ad);
   evas\_object\_smart\_callback\_add(entry, \textcolor{stringliteral}{"activated"}, \_search\_entry\_activate\_cb,
                                  ad);

   box2 = elm_box_add(ad->win);
   elm\_box\_horizontal\_set(box2, EINA\_TRUE);
   elm_object_part_content_set(entry, \textcolor{stringliteral}{"end"}, box2);

   btn = elm_button_add(ad->win);
   elm\_box\_pack\_end(box2, btn);
   evas\_object\_show(btn);

   ic = elm_icon_add(ad->win);
   elm\_icon\_standard\_set(ic, \textcolor{stringliteral}{"arrow\_up"});
   elm_object_part_content_set(btn, \textcolor{stringliteral}{"icon"}, ic);

   evas\_object\_smart\_callback\_add(btn, \textcolor{stringliteral}{"clicked"}, \_search\_prev\_cb, ad);

   btn = elm_button_add(ad->win);
   elm\_box\_pack\_end(box2, btn);
   evas\_object\_show(btn);

   ic = elm_icon_add(ad->win);
   elm\_icon\_standard\_set(ic, \textcolor{stringliteral}{"arrow\_down"});
   elm_object_part_content_set(btn, \textcolor{stringliteral}{"icon"}, ic);

   evas\_object\_smart\_callback\_add(btn, \textcolor{stringliteral}{"clicked"}, \_search\_next\_cb, ad);

   btn = elm_button_add(ad->win);
   elm\_box\_pack\_end(box, btn);
   evas\_object\_show(btn);

   ic = elm_icon_add(ad->win);
   elm\_icon\_standard\_set(ic, \textcolor{stringliteral}{"close"});
   elm_object_part_content_set(btn, \textcolor{stringliteral}{"icon"}, ic);

   evas\_object\_smart\_callback\_add(btn, \textcolor{stringliteral}{"clicked"}, \_search\_close\_cb, ad);

   ad->search\_box = box;
   ad->search\_entry = entry;

   elm_object_focus_set(entry, EINA\_TRUE);
\}

\end{DoxyCodeInclude}


Last, create the main window and put all of the things used above in it. It contains a default web widget that will be shown when no tabs exist. This web object is not browsable per se, so history is disabled in it, and we set the same callback to create new windows, on top of setting some custom content of our own on it, with some links that will open new tabs to start browsing quickly.


\begin{DoxyCodeInclude}
\textcolor{keyword}{static} \textcolor{keywordtype}{void}
default\_content\_set(Evas\_Object *web)
\{
\textcolor{preprocessor}{#ifdef HAVE\_ELEMENTARY\_WEB}
   Evas\_Object *view, *frame;
   \textcolor{keyword}{const} \textcolor{keywordtype}{char} contents[] = \textcolor{stringliteral}{""}
      \textcolor{stringliteral}{"<html>\(\backslash\)n"}
      \textcolor{stringliteral}{"  <head>\(\backslash\)n"}
      \textcolor{stringliteral}{"    <title>Nothing to see here, move along</title>\(\backslash\)n"}
      \textcolor{stringliteral}{"  </head>\(\backslash\)n"}
      \textcolor{stringliteral}{"  <body>\(\backslash\)n"}
      \textcolor{stringliteral}{"    <a href=\(\backslash\)"http://www.enlightenment.org\(\backslash\)" target=\(\backslash\)"\_blank\(\backslash\)">E</a>\(\backslash\)n"}
      \textcolor{stringliteral}{"    <br />\(\backslash\)n"}
      \textcolor{stringliteral}{"    <a href=\(\backslash\)"http://www.google.com\(\backslash\)" target=\(\backslash\)"\_blank\(\backslash\)">Google</a>\(\backslash\)n"}
      \textcolor{stringliteral}{"    <br />\(\backslash\)n"}
      \textcolor{stringliteral}{"  </body>\(\backslash\)n"}
      \textcolor{stringliteral}{"</html>\(\backslash\)n"};

   view = elm\_web\_webkit\_view\_get(web);
   frame = ewk\_view\_frame\_main\_get(view);
   ewk\_frame\_contents\_set(frame, contents, \textcolor{keyword}{sizeof}(contents) - 1, \textcolor{stringliteral}{"text/html"},
                          \textcolor{stringliteral}{"UTF-8"}, NULL);
\textcolor{preprocessor}{#else}
   (void) web;
\textcolor{preprocessor}{#endif}
\}

EAPI\_MAIN \textcolor{keywordtype}{int}
elm\_main(\textcolor{keywordtype}{int} argc, \textcolor{keywordtype}{char} *argv[])
\{
   Evas\_Object *win, *box, *box2, *btn, *ic, *url\_bar, *naviframe, *tabs, *web;
   Evas *e;
   Evas\_Modifier\_Mask ctrl\_mask;
   App\_Data *ad;

   \textcolor{keywordflow}{if} (!elm_need_web())
     \textcolor{keywordflow}{return} -1;

   ad = calloc(1, \textcolor{keyword}{sizeof}(App\_Data));
   \textcolor{keywordflow}{if} (!ad) \textcolor{keywordflow}{return} -1;

   elm_policy_set(ELM\_POLICY\_QUIT, ELM\_POLICY\_QUIT\_LAST\_WINDOW\_CLOSED);

   win = elm_win_util_standard_add(\textcolor{stringliteral}{"example-web"}, \textcolor{stringliteral}{"Web Example"});
   elm\_win\_autodel\_set(win, EINA\_TRUE);

   e = evas\_object\_evas\_get(win);
   ctrl\_mask = evas\_key\_modifier\_mask\_get(e, \textcolor{stringliteral}{"Control"});
   \textcolor{keywordflow}{if} (!evas\_object\_key\_grab(win, \textcolor{stringliteral}{"f"}, ctrl\_mask, 0, EINA\_TRUE))
     fprintf(stderr, \textcolor{stringliteral}{"Could not grab trigger for search dialog\(\backslash\)n"});

   evas\_object\_smart\_callback\_add(win, \textcolor{stringliteral}{"delete,request"}, \_win\_del\_request\_cb,
                                  ad);
   evas\_object\_event\_callback\_add(win, EVAS\_CALLBACK\_KEY\_DOWN,
                                  \_win\_search\_trigger\_cb, ad);
   evas\_object\_event\_callback\_add(win, EVAS\_CALLBACK\_FREE, \_win\_free\_cb, ad);

   box = elm_box_add(win);
   evas\_object\_size\_hint\_weight\_set(box, EVAS\_HINT\_EXPAND, EVAS\_HINT\_EXPAND);
   elm\_win\_resize\_object\_add(win, box);
   evas\_object\_show(box);

   url\_bar = elm_entry_add(win);
   elm\_entry\_single\_line\_set(url\_bar, EINA\_TRUE);
   elm\_entry\_scrollable\_set(url\_bar, EINA\_TRUE);
   evas\_object\_size\_hint\_weight\_set(url\_bar, EVAS\_HINT\_EXPAND, 0.0);
   evas\_object\_size\_hint\_align\_set(url\_bar, EVAS\_HINT\_FILL, EVAS\_HINT\_FILL);
   elm\_box\_pack\_end(box, url\_bar);
   evas\_object\_show(url\_bar);

   evas\_object\_smart\_callback\_add(url\_bar, \textcolor{stringliteral}{"activated"}, \_url\_entry\_activated\_cb, ad);

   box2 = elm_box_add(win);
   elm\_box\_horizontal\_set(box2, EINA\_TRUE);
   elm_object_part_content_set(url\_bar, \textcolor{stringliteral}{"icon"}, box2);
   elm\_entry\_icon\_visible\_set(url\_bar, EINA\_FALSE);

   btn = elm_button_add(win);
   elm\_box\_pack\_end(box2, btn);
   evas\_object\_show(btn);

   ad->nav.back = btn;

   ic = elm_icon_add(win);
   elm\_icon\_standard\_set(ic, \textcolor{stringliteral}{"arrow\_left"});
   elm_object_part_content_set(btn, \textcolor{stringliteral}{"icon"}, ic);

   evas\_object\_smart\_callback\_add(btn, \textcolor{stringliteral}{"clicked"}, \_nav\_back\_cb, ad);

   btn = elm_button_add(win);
   elm\_box\_pack\_end(box2, btn);
   evas\_object\_show(btn);

   ad->nav.refresh = btn;

   ic = elm_icon_add(win);
   elm\_icon\_standard\_set(ic, \textcolor{stringliteral}{"refresh"});
   elm_object_part_content_set(btn, \textcolor{stringliteral}{"icon"}, ic);

   evas\_object\_smart\_callback\_add(btn, \textcolor{stringliteral}{"clicked"}, \_nav\_refresh\_cb, ad);

   btn = elm_button_add(win);
   elm\_box\_pack\_end(box2, btn);
   evas\_object\_show(btn);

   ad->nav.fwd = btn;

   ic = elm_icon_add(win);
   elm\_icon\_standard\_set(ic, \textcolor{stringliteral}{"arrow\_right"});
   elm_object_part_content_set(btn, \textcolor{stringliteral}{"icon"}, ic);

   evas\_object\_smart\_callback\_add(btn, \textcolor{stringliteral}{"clicked"}, \_nav\_fwd\_cb, ad);

   box2 = elm_box_add(win);
   elm\_box\_horizontal\_set(box2, EINA\_TRUE);
   evas\_object\_size\_hint\_weight\_set(box2, EVAS\_HINT\_EXPAND, 0.0);
   evas\_object\_size\_hint\_align\_set(box2, EVAS\_HINT\_FILL, EVAS\_HINT\_FILL);
   elm\_box\_pack\_end(box, box2);
   evas\_object\_show(box2);

   btn = elm_button_add(win);
   elm\_box\_pack\_end(box2, btn);
   evas\_object\_show(btn);

   ic = elm_icon_add(win);
   elm\_icon\_standard\_set(ic, \textcolor{stringliteral}{"file"});
   elm_object_part_content_set(btn, \textcolor{stringliteral}{"icon"}, ic);

   evas\_object\_smart\_callback\_add(btn, \textcolor{stringliteral}{"clicked"}, \_add\_tab\_cb, ad);

   tabs = elm_toolbar_add(win);
   elm\_toolbar\_align\_set(tabs, 0.0);
   elm\_toolbar\_select\_mode\_set(tabs, ELM\_OBJECT\_SELECT\_MODE\_ALWAYS);
   elm\_toolbar\_homogeneous\_set(tabs, EINA\_FALSE);
   elm\_toolbar\_shrink\_mode\_set(tabs, ELM\_TOOLBAR\_SHRINK\_MENU);
   evas\_object\_size\_hint\_weight\_set(tabs, EVAS\_HINT\_EXPAND, EVAS\_HINT\_EXPAND);
   evas\_object\_size\_hint\_align\_set(tabs, EVAS\_HINT\_FILL, EVAS\_HINT\_FILL);
   elm\_box\_pack\_end(box2, tabs);
   evas\_object\_show(tabs);

   btn = elm_button_add(win);
   elm\_box\_pack\_end(box2, btn);
   evas\_object\_show(btn);

   evas\_object\_smart\_callback\_add(btn, \textcolor{stringliteral}{"clicked"}, \_close\_tab\_cb, ad);

   ic = elm_icon_add(win);
   elm\_icon\_standard\_set(ic, \textcolor{stringliteral}{"close"});
   elm_object_part_content_set(btn, \textcolor{stringliteral}{"icon"}, ic);

   naviframe = elm_naviframe_add(win);
   evas\_object\_size\_hint\_weight\_set(naviframe, EVAS\_HINT\_EXPAND, EVAS\_HINT\_EXPAND);
   evas\_object\_size\_hint\_align\_set(naviframe, EVAS\_HINT\_FILL, EVAS\_HINT\_FILL);
   elm\_box\_pack\_end(box, naviframe);
   evas\_object\_show(naviframe);

   elm\_toolbar\_menu\_parent\_set(tabs, naviframe);

   web = elm_web_add(win);
   elm\_web\_window\_create\_hook\_set(web, \_web\_create\_window\_cb, ad);
   elm\_web\_history\_enabled\_set(web, EINA\_FALSE);
   evas\_object\_size\_hint\_weight\_set(web, EVAS\_HINT\_EXPAND, EVAS\_HINT\_EXPAND);
   evas\_object\_size\_hint\_align\_set(web, EVAS\_HINT\_FILL, EVAS\_HINT\_FILL);
   elm\_naviframe\_item\_simple\_push(naviframe, web);

   default\_content\_set(web);

   ad->win = win;
   ad->main\_box = box;
   ad->naviframe = naviframe;
   ad->url\_entry = url\_bar;
   ad->default\_web = web;
   ad->tabs = tabs;
   ad->close\_tab = btn;

   evas\_object\_resize(win, 480, 640);
   evas\_object\_show(win);

   elm_run();

   \textcolor{keywordflow}{return} 0;
\}
ELM_MAIN()

\end{DoxyCodeInclude}


Some parts of the code were left out, as they are not relevant to the example, but the full listing can be found at \hyperlink{web_example_02_8c-example}{web\+\_\+example\+\_\+02.c}. 