Open Source/EFL

Hello ewebkit?

소혼 2014. 3. 14. 08:44
반응형

ewebkit은 WebKit 엔진 기반에 EFL 라이브러리를 사용하여 UI를 표현하는 라이브러리입니다.

(WebKit/EFL 이라고도 부르는데,  저는 so 파일 이름에 따라 ewebkit이라고 부르고 있습니다.)


물론,  Elementary의 elm_web이 ewebkit 에서 사용하는 ewk_view의 간단한 wrapper 클래스이지만 아직 문제가 많은 상태이기 때문에(1.9) ewebkit을 직접 쓰는 방법을 권장하고 있습니다. (또 타이젠(~2.2) 에서는 elm_web을 사용하실 수 없습니다.)

이 글에서는 elm_web이 아닌 ewk_view를 사용해서 간단한 페이지를 만드는 법을 공유하려고 합니다.


ewebkit 라이브러리는 현재 두 종류가 있습니다.

ewebkit : WebKit1/EFL 포트에 기반하는 라이브러리

ewebkit2 : WebKit2/EFL 포트에 기반하는 라이브러리


둘의 가장 큰 차이는 간단히 설명드리면 웹페이지를 렌더링하는 코어영역을 같은 프로세스에서 처리하느냐(ewebkit), 다른 프로세스에서 처리하느냐(ewebkit2) 입니다.

대부분의 인터페이스는 유사하지만, 이런 프로세스 모델의 차이에서 몇몇 인터페이스에는 차이가 있습니다.


참고로 타이젠과 같은 경우 1.0에서는 ewebkit을 사용하였고, 2.0부터는 ewebkit2를 사용하고 있습니다.

(현재 ewebkit은 webkit.org에서 제거되어 ewebkit2만 남았습니다.)


ewebkit을 사용한 코드들은 elm_web (http://git.enlightenment.org/core/elementary.git/tree/src/lib/elm_web.c) 이나 WebKit 프로젝트 내의 http://trac.webkit.org/browser/trunk/Tools/EWebLauncher/main.c 가있습니다.

ewebkit2를 사용한 코드들은 elm_web2(http://git.enlightenment.org/core/elementary.git/tree/src/lib/elm_web2.c),  또는 WebKit 프로젝트 내의 http://trac.webkit.org/browser/trunk/Tools/MiniBrowser/efl/main.c 가 있습니다.


참고삼아 보시면 될 듯 하고, 이 글에서는 ewebkit2 의 코드를 MiniBrowser 기반으로 설명을 드리려고 합니다.

(http://trac.webkit.org/browser/trunk/Tools/MiniBrowser/efl/main.c 정도의 설명입니다.)


혹시 EFL 에 대해서 잘 모르신다면, 이 글을 읽기에 부담스러우실 수 있습니다.

(과감히 뒤로가기를 누르셔도 됩니다.)


(

혹, EFL에 관심이 있으시면 먼저 아래 글을 보시는 것을 추천드립니다.

https://events.linuxfoundation.org/images/stories/pdf/lfcs2012_raster.pdf

)


1. 생성 / 소멸

다른 EFL 라이브러리들처럼 ewebkit/ewebkit2도 전역의  _init 과  _shutdown 을 가지고 있습니다.


### c++

int main ()

{

    ewk_init();

    ...

    ewk_shutdown();

    return 0;

}

반드시 사용하기 전에 호출해주셔야 합니다.

가능하면 main 시작하자마자 ewk_init을 호출하고, loop가 끝난 후 ewk_shutdown을 호출해주시는 것이 좋습니다.


다음으로,ewk_view 객체를 만들어야 합니다.

ewk_view를 만드는 방법은 여러가지가 있습니다. 하나씩 살펴보도록 하겠습니다.


1) ewk_view_add(Evas *e)

ewk_view_add 는 ewk_view를 만드는 가장 쉬운 방법입니다.

간단한 페이지를 로드하는 데는 적합하지만, alert/prompt/confirm이라던가 새창을 열거나 그 밖에 UI의 도움을 받아야 하는 많은 것들을 할 수 없습니다.

또, ewebkit에서는 관계없으나 ewebkit2에서는 매 evas object가 별도의 WebProcess를 생성하여 동작하게 됩니다.


### c++

Evas_Object *o = ewk_view_add(e);

ewk_view_url_set(o, "http://bunhere.tistory.com");


2) ewk_view_add_with_context(Evas *e, Ewk_Context *context)

ewebkit에서는 없는 함수입니다.

ewebkit2에서는 web context 라는 것이 있어서 하나의 web context는 하나의 WebProcess를 생성하게 합니다. 만약 이미 생성한 web context 안에 웹뷰를 만들려고 하면 이 함수를 사용해서 생성하면 됩니다.


### c++

// o 와 같은 context(web process)에서 동작하는 ewk_view를 생성

Evas_Object *o2 = ewk_view_add_with_context(e, ewk_view_context_get(o));


3) ewk_view_smart_add(Evas *e, Evas_Smart *smart, Ewk_Context *context, Ewk_Page_Group *group)

해당 API는 ewebkit에는 없습니다.(유사한 방법이 있으나 별도의 API 로 존재하지 않습니다.)


이 API 를 쓰면 ewk_view가 할 수 있는 일을 모두 할 수 있습니다.

물론 그만큼 사용하기 어렵다는 문제도 있습니다.


먼저, 인자들을 하나씩 살펴보도록 하겠습니다.

Evas *e

현재 생성하는 ewk_view의 기반이 될 canvas입니다.


Evas_Smart *smart

ewk_view는 여러 Evas_Object들 중 smart object로 만들어졌습니다.

Smart Object를 만드는 것에 대한 자세한 내용은 아래 글을 참고하시면 좋을 것 같습니다.

http://docs.enlightenment.org/stable/efl/Example_Evas_Smart_Objects.html


일반적으로 smart object를 만들때는 smart class를 만들어서 evas_object_smart_add를 호출하면 되지만, ewk_view는 추가로 처리해야 하는 인자들이 있어서 ewk_view_smart_add를 대신 사용합니다.

ewk_view_smart_add는 내부적으로 evas_object_smart_add의 일을 수행하게 됩니다.

(ewebkit은 evas_object_smart_add를 사용합니다.)

Evas_Smart를 만드는 법은 복잡하기 때문에 아래에서 다시 설명하겠습니다.


Ewk_Context *context

여러 ewk_view는 하나의 context를 가질 수도 있고, 여러개의 context를 가질 수도 있습니다.

하나의 context에 기반한 ewk_view들은 많은 것을 공유하게 됩니다.

특히 하나의 프로세스에서 수행되게 될 것입니다.

context를 구하려면 기존의 ewk_view 를 이용하여 ewk_view_context_get(o)을 하거나, ewk_context_default_get()을 이용하여 default context를 생성하면 됩니다.


Ewk_Page_Group *group

page group을 이해하는 쉬운 예제는 자바스크립트로 실행한 새창입니다. 자바스크립트로 새창을 열면 해당 페이지와 새로 열린 페이지는 opener / child 관계를 갖게 됩니다. 이 두 페이지는 같은 세팅을 가져야 합니다. 세션도 공유할 것이고요.

이렇게 같은 설정을 가져야 하고 정보들을 공유해야 한다면 같은 page group으로 묶어야 합니다.

page group을 얻는 방법은 기존의 ewk_view를 이용하여 ewk_view_page_group(o)을 호출하거나 ewk_page_group_create(group_name) 을 호출하여 특정 그룹을 생성하면 됩니다. group_name이 null이면 임의의 그룹을 생성하게 됩니다.


Evas_Smart 만들기

Evas_Smart를 만들려면 smart class를 하나 만들어야 합니다.

특히 ewk_view를 위한 smart class는 Evas_Smart_Class 를 확장한 Ewk_View_Smart_Class입니다.

사용자는 Ewk_View_Smart_Class를 확장하거나, Ewk_View_Smart_Class를 고쳐서 쓸 수 있습니다.

확장을 해서 쓸 경우, 기본 구현을 오버라이드하여 이용하기 좋다는 장점이 있습니다만, 대부분의 경우에는 기본 구현이 없습니다.(마우스/터치 이벤트 제외)


이 글에서는 일단 Ewk_View_Smart_Class를 고쳐서 쓰려고 합니다.

###  c++

static Ewk_View_Smart_Class *miniBrowserViewSmartClass()                                                                                                                 
{
    static Ewk_View_Smart_Class ewkViewClass = EWK_VIEW_SMART_CLASS_INIT_NAME_VERSION("MiniBrowser_View");
    return &ewkViewClass;
}

MiniBrowser에서 발췌한 코드로 Ewk_View_Smart_Class 객체를 하나 만들어서 MiniBrowser_View라는 이름으로 초기화했습니다.

이 때, 값들은 모두 NULL로 초기화 될 것입니다.

ewk_view가 제공하는 메소드들로 재정의하기 위해서 ewk_view_smart_class_set을 호출해 주어야 합니다.

사실 ewk_view는 재정의할 메소드들이 별로 없습니다만 이 함수는 반드시 호출되어야 합니다. 가장 중요한 Evas_Smart_Class의 메소드들이 연결될 것입니다.

### c++

    if (!ewk_init())
        return EXIT_FAILURE;

    ewk_view_smart_class_set(miniBrowserViewSmartClass());


이제 어플리케이션에서 필요로 하는 기능들에 대해 추가로 수정을 하시면 됩니다.

### c++

    Ewk_View_Smart_Class *ewkViewClass = miniBrowserViewSmartClass();                                                                                                    
    ewkViewClass->run_javascript_alert = on_javascript_alert;
    ewkViewClass->run_javascript_confirm = on_javascript_confirm;
    ewkViewClass->run_javascript_prompt = on_javascript_prompt;
    ewkViewClass->window_geometry_get = on_window_geometry_get;
    ewkViewClass->window_geometry_set = on_window_geometry_set;
    ewkViewClass->fullscreen_enter = on_fullscreen_enter;
    ewkViewClass->fullscreen_exit = on_fullscreen_exit;
    ewkViewClass->window_create = on_window_create;
    ewkViewClass->window_close = on_window_close;
    ewkViewClass->popup_menu_show = on_popup_menu_show;
    ewkViewClass->popup_menu_hide = on_popup_menu_hide;
    ewkViewClass->context_menu_show = on_context_menu_show;
    ewkViewClass->context_menu_hide = on_context_menu_hide;
    ewkViewClass->input_picker_color_request = on_color_picker_request;
    ewkViewClass->input_picker_color_dismiss = on_color_picker_dismiss;

앞서 말씀 드린 것과 같이 마우스 이벤트와 같은 몇몇 이벤트를 제외하면 ewkViewClass가 추가한 메소드들은 특수한 구현들을 갖고 있지 않습니다.


각각의 메소드들이 어떤 인자들과 반환값을 가져야 하는지는 http://trac.webkit.org/browser/trunk/Source/WebKit2/UIProcess/API/efl/ewk_view.h 를 참고하셔야 합니다.

몇몇 메소드들은 아래에서 좀 더 설명하도록 하겠습니다.


이렇게 smart class가 준비되었다면 Evas_Smart를 만들면 됩니다.

### c++

Evas_Smart *smart = evas_smart_class_new(&ewkViewClass->sc);

sc는 Evas_Smart_Class를 가르키는 주소입니다.


아래는 MiniBrowser에서 ewk_view_smart_add를 호출하는 일부 코드입니다..

### c++

    Evas *evas = evas_object_evas_get(window->elm_window);
    Evas_Smart *smart = evas_smart_class_new(&ewkViewClass->sc);
    Ewk_Context *context = opener ? ewk_view_context_get(opener) : ewk_context_default_get();
    Ewk_Page_Group *pageGroup = opener ? ewk_view_page_group_get(opener) : ewk_page_group_create("");
    window->ewk_view = ewk_view_smart_add(evas, smart, context, pageGroup);


생성과 달리 소멸은 간단히 evas_object_del을 호출해주면 됩니다.


2. Load contents

ewebkit에서 contents를 읽는 방법은 두가지가 있습니다.
가장 기본적인 방법인 url을 읽는 방법과, html string을 읽는 방법입니다.


url을 읽는 API는 다음과 같습니다.

### c++

ewk_view_url_set(view, "http://bunhere.tistory.com");

그 다음은 알아서 로딩이 된 후, 화면에 그려지게 됩니다.


html string을 직접 읽는 방법도 크게 어렵지는 않습니다.

### c++

ewk_view_html_string_load(view, "<!doctype html><body>hello</body>", base_uri, unreachable_uri);

img나 기타 리소스들이 상대 경로로 놓여질 때 읽어올 base_uri, 에러가 났을때 알려줄 unreachable_uri가 추가된 것을 제외하면 특별한 것이 없습니다. 그리고 이 값들은 NULL로 넘겨도 상관없습니다.


간단한 예제


여기까지 이야기한 것들을 바탕으로 가장 간단한 ewebkit 기반의 웹브라우저를 만들어보겠습니다.

https://github.com/ewebkit/samples/blob/master/devs/ryuan/simple.c

### c++

// gcc simplebutton.cpp `pkg-config --cflags --libs elementary ewebkit2`           
#include <Elementary.h>                                                            
#include <EWebKit2.h>                                                              
                                                                                   
void on_done(void *userData, Evas_Object *webView, void *eventInfo)
{
   elm_exit();
}

EAPI_MAIN int
elm_main(int argc, char *argv[])
{
   ewk_init();

   Evas_Object* win;
   win = elm_win_add(NULL, "sample", ELM_WIN_BASIC);
   elm_win_title_set(win, "sample");
   evas_object_smart_callback_add(win, "delete,request", on_done, NULL);
   elm_win_autodel_set(win, EINA_TRUE);

   Evas_Object* bg = elm_bg_add(win);
   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
   elm_bg_color_set(bg, 0, 0, 255);
   elm_win_resize_object_add(win, bg);
   evas_object_show(bg);

   Evas_Object* ewk = ewk_view_add(evas_object_evas_get(win));
   ewk_view_url_set(ewk, "http://bunhere.tistory.com");

   evas_object_resize(ewk, 400, 400);
   evas_object_move(ewk, 0, 0);
   evas_object_show(ewk);

   evas_object_resize(win, 400, 400);
   evas_object_show(win);

   elm_run();

   ewk_shutdown();                                                                                                                                                      
}                                                                                  
ELM_MAIN()


실행 결과입니다.



반응형

'Open Source > EFL' 카테고리의 다른 글

[EFL] EWebKit Extension  (0) 2014.09.23
transparent ewebkit  (0) 2014.07.30
WebKit/efl 하면서 쓸 ctags 만들기  (0) 2013.12.17
Elementary Dark theme  (0) 2013.10.17
[TIZEN][EFL] 타이젠 상에서 EFL 예제 실행하기  (9) 2013.08.02