From: barbieri Date: Wed, 5 Oct 2011 22:18:22 +0000 (+0000) Subject: Elementary support for EWS, with simplistic window manager. X-Git-Tag: REL_F_I9500_20120323_1~17^2~1697 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=1e327365b7b608ecd5e60ad6610e841f1d14ecbb;p=framework%2Fuifw%2Felementary.git Elementary support for EWS, with simplistic window manager. This contains a very simple and stupid window manager to be used in FB, PS3 or similar single-window engines. Everybody is welcome to improve it, particularly: * Edje: better border decoration theme * Edje: nice background * C + Edje: taskbar with minimized items. * C + Edje: find a better protocol to determine window size, accounting border decoration without account shadow! Right now I'm taking everything :-P * C: window management keys (Alt+F4 and like) How to use: export ELM_ENGINE=ews How to configure backing store: export ECORE_EVAS_EWS=engine:x:y:w:h:options Example: {{{ export ECORE_EVAS_EWS=software_x11:0:0:1024:768 export ELM_ENGINE=ews elementary_test }}} Bugs: maybe many, but so far seems it wouldn't take mouse events for secondary windows. Will check it later. git-svn-id: svn+ssh://svn.enlightenment.org/var/svn/e/trunk/elementary@63849 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33 --- diff --git a/data/themes/Makefile.am b/data/themes/Makefile.am index f145f6f..7496bfc 100644 --- a/data/themes/Makefile.am +++ b/data/themes/Makefile.am @@ -60,6 +60,7 @@ widgets/win.edc \ widgets/entry.edc \ widgets/map.edc \ widgets/scroller.edc \ +ews.edc \ arrow_down.png \ arrow_up.png \ bar_shine.png \ diff --git a/data/themes/default.edc b/data/themes/default.edc index d362756..f24beb0 100644 --- a/data/themes/default.edc +++ b/data/themes/default.edc @@ -365,4 +365,6 @@ collections { #include "widgets/video.edc" #include "widgets/naviframe.edc" +#include "ews.edc" + } diff --git a/data/themes/ews.edc b/data/themes/ews.edc new file mode 100644 index 0000000..c3e70fe --- /dev/null +++ b/data/themes/ews.edc @@ -0,0 +1,317 @@ +group { name: "elm/ews/background/default"; + parts { + part { name: "base"; + type: RECT; + mouse_events: 0; + description { state: "default" 0.0; + color: 64 64 64 255; + } + } + } +} + +/* + Border Decorations Protocol: + + Receive Signals: all use "elm" as source + - elm,state,focus,{on,off} + - elm,state,iconified,{on,off} + - elm,state,maximized,{on,off} + - elm,state,fullscreen,{on,off} + - elm,state,alpha,{on,off} + + Send Signals: + - elm,action,focus + - elm,action,iconify + - elm,action,maximize + - elm,action,fullscreen + - elm,action,restore - remove iconified, maximized or fullscreen + - elm,action,close + - elm,action,menu + - elm,action,move,start + - elm,action,move,stop + + Parts: + - elm.text.title + - elm.text.name + - elm.text.class + */ + +images { + image: "shadow.png" COMP; + image: "icon_close.png" COMP; + image: "icon_arrow_up_right.png" COMP; + image: "icon_arrow_down_left.png" COMP; +} + +group { name: "elm/ews/decoration/borderless"; + parts { + part { name: "shadow"; + type: IMAGE; + mouse_events: 0; + description { state: "default" 0.0; + image { + normal: "shadow.png"; + border: 13 13 13 13; + middle: 0; + } + rel1 { + to: "base"; + offset: -11 -9; + } + rel2 { + to: "base"; + offset: 11 11; + } + fill.smooth: 0; + } + description { state: "hidden" 0.0; + inherit: "default" 0.0; + visible: 0; + } + } + programs { + program { signal: "elm,state,alpha,on"; + source: "elm"; + action: STATE_SET "hidden" 0.0; + target: "shadow"; + } + program { signal: "elm,state,alpha,off"; + source: "elm"; + action: STATE_SET "visible" 0.0; + target: "shadow"; + } + } + + part { name: "base"; + type: RECT; + mouse_events: 0; + description { state: "default" 0.0; + color: 0 0 0 255; + } + } + } +} + +group { name: "elm/ews/decoration/default"; + parts { + part { name: "shadow"; + type: IMAGE; + mouse_events: 0; + description { state: "default" 0.0; + image { + normal: "shadow.png"; + border: 13 13 13 13; + middle: 0; + } + rel1 { + to: "base"; + offset: -11 -9; + } + rel2 { + to: "base"; + offset: 11 11; + } + fill.smooth: 0; + } + description { state: "hidden" 0.0; + inherit: "default" 0.0; + visible: 0; + } + } + programs { + program { signal: "elm,state,alpha,on"; + source: "elm"; + action: STATE_SET "hidden" 0.0; + target: "shadow"; + } + program { signal: "elm,state,alpha,off"; + source: "elm"; + action: STATE_SET "visible" 0.0; + target: "shadow"; + } + } + + part { name: "base"; + type: RECT; + mouse_events: 0; + description { state: "default" 0.0; + // TODO: make me a nice image! + color: 200 200 200 255; + rel1.offset: -2 -32; + rel2.offset: 1 1; + } + } + + part { name: "base-text"; + type: RECT; + mouse_events: 1; + description { state: "default" 0.0; + color: 0 0 0 0; + rel1.to: "base"; + rel2 { + offset: -2 -1; + relative: 0.0 0.0; + to_x: "base-buttons"; + } + } + } + programs { + program { signal: "mouse,down,1"; + source: "base-text"; + action: SIGNAL_EMIT "elm,action,move,start" "elm"; + } + program { signal: "mouse,up,1"; + source: "base-text"; + action: SIGNAL_EMIT "elm,action,move,stop" "elm"; + } + } + + part { name: "elm.text.title"; + type: TEXT; + effect: SHADOW; + mouse_events: 0; + description { state: "default" 0.0; + color: 255 255 255 255; + color3: 0 0 0 255; + rel1 { + to: "base-text"; + offset: 5 2; + } + rel2 { + to: "base-text"; + offset: -6 -3; + } + text { + font: "Sans:style=Bold"; + size: 12; + align: 0.0 0.5; + } + } + } + + part { name: "base-buttons"; + type: RECT; + mouse_events: 0; + description { state: "default" 0.0; + color: 255 255 255 0; + rel1 { + to: "base"; + relative: 1.0 0.0; + offset: (-24 * 3 -1) 0; + } + rel2 { + relative: 1.0 0.0; + offset: -1 -1; + } + } + } + + part { name: "restore"; + type: IMAGE; + mouse_events: 1; + description { state: "default" 0.0; + image.normal: "icon_arrow_down_left.png"; + min: 24 24; + max: 24 24; + rel1 { + to: "base-buttons"; + relative: 1.0 0.0; + offset: (-24 * 3 - 1) 0; + } + rel2 { + to: "base-buttons"; + relative: 1.0 1.0; + offset: (-24 * 2 - 1) 0; + } + } + } + programs { + program { signal: "mouse,clicked,1"; + source: "restore"; + action: SIGNAL_EMIT "elm,action,restore" "elm"; + } + } + + part { name: "maximize"; + type: IMAGE; + mouse_events: 0; + description { state: "default" 0.0; + image.normal: "icon_arrow_up_right.png"; + min: 24 24; + max: 24 24; + rel1 { + to: "base-buttons"; + relative: 1.0 0.0; + offset: (-24 * 2 - 1) 0; + } + rel2 { + to: "base-buttons"; + relative: 1.0 1.0; + offset: (-24 * 1 - 1) 0; + } + } + description { state: "maximized" 0.0; + inherit: "default" 0.0; + color: 255 255 255 96; + } + } + part { name: "maximize-eventarea"; + type: RECT; + mouse_events: 1; + description { state: "default" 0.0; + color: 0 0 0 0; + rel1.to: "maximize"; + rel2.to: "maximize"; + } + description { state: "maximized" 0.0; + inherit: "default" 0.0; + visible: 0; + } + } + programs { + program { signal: "mouse,clicked,1"; + source: "maximize-eventarea"; + action: SIGNAL_EMIT "elm,action,maximize" "elm"; + } + program { signal: "elm,state,maximized,on"; + source: "elm"; + action: STATE_SET "maximized" 0.0; + target: "maximize-eventarea"; + target: "maximize"; + } + program { signal: "elm,state,maximized,off"; + source: "elm"; + action: STATE_SET "default" 0.0; + target: "maximize-eventarea"; + target: "maximize"; + } + } + + part { name: "close"; + type: IMAGE; + mouse_events: 1; + description { state: "default" 0.0; + image.normal: "icon_close.png"; + min: 24 24; + max: 24 24; + rel1 { + to: "base-buttons"; + relative: 1.0 0.0; + offset: (-24 * 1 - 1) 0; + } + rel2 { + to: "base-buttons"; + relative: 1.0 1.0; + offset: (-24 * 0 - 1) 0; + } + } + } + programs { + program { signal: "mouse,clicked,1"; + source: "close"; + action: SIGNAL_EMIT "elm,action,close" "elm"; + } + } + } +} diff --git a/src/lib/Elementary.h.in b/src/lib/Elementary.h.in index 372687c..b37ae53 100644 --- a/src/lib/Elementary.h.in +++ b/src/lib/Elementary.h.in @@ -1889,6 +1889,7 @@ extern "C" { * @li "software_16_sdl" * @li "opengl_sdl" * @li "buffer" + * @li "ews" * * @{ */ @@ -3518,6 +3519,7 @@ extern "C" { * (Windows CE rendering via GDI with 16bit software renderer) * @li "sdl-16", "software-16-sdl", "software_16_sdl" (Rendering to SDL * buffer with 16bit software renderer) + * @li "ews" (rendering to EWS - Ecore + Evas Single Process Windowing System) * * All engines use a simple string to select the engine to render, EXCEPT * the "shot" engine. This actually encodes the output of the virtual diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am index 941ce64..c6b02dd 100644 --- a/src/lib/Makefile.am +++ b/src/lib/Makefile.am @@ -125,7 +125,8 @@ els_pan.c \ els_pan.h \ els_scroller.c \ els_scroller.h \ -els_tooltip.c +els_tooltip.c \ +elu_ews_wm.c libelementary_la_CFLAGS = libelementary_la_LIBADD = \ diff --git a/src/lib/elm_config.c b/src/lib/elm_config.c index a6c76f3..59aec78 100644 --- a/src/lib/elm_config.c +++ b/src/lib/elm_config.c @@ -31,6 +31,7 @@ const char *_elm_engines[] = { "software_16_sdl", "opengl_sdl", "buffer", + "ews", NULL }; @@ -1469,6 +1470,8 @@ _env_get(void) eina_stringshare_replace(&_elm_config->engine, ELM_BUFFER); else if ((!strncmp(s, "shot:", 5))) eina_stringshare_replace(&_elm_config->engine, s); + else if ((!strcasecmp(s, "ews"))) + eina_stringshare_replace(&_elm_config->engine, ELM_EWS); } s = getenv("ELM_VSYNC"); diff --git a/src/lib/elm_main.c b/src/lib/elm_main.c index 5f19d5d..ebb01ee 100644 --- a/src/lib/elm_main.c +++ b/src/lib/elm_main.c @@ -79,6 +79,7 @@ _elm_rescale(void) { edje_scale_set(_elm_config->scale); _elm_win_rescale(NULL, EINA_FALSE); + _elm_ews_wm_rescale(NULL, EINA_FALSE); } static void *app_mainfunc = NULL; @@ -425,6 +426,7 @@ elm_quicklaunch_sub_init(int argc, ecore_imf_init(); ecore_con_init(); ecore_con_url_init(); + _elm_ews_wm_init(); } return _elm_sub_init_count; } @@ -444,6 +446,7 @@ elm_quicklaunch_sub_shutdown(void) { _elm_win_shutdown(); _elm_module_shutdown(); + _elm_ews_wm_shutdown(); ecore_con_url_shutdown(); ecore_con_shutdown(); ecore_imf_shutdown(); @@ -458,7 +461,8 @@ elm_quicklaunch_sub_shutdown(void) ENGINE_COMPARE(ELM_SOFTWARE_16_SDL) || ENGINE_COMPARE(ELM_OPENGL_SDL) || ENGINE_COMPARE(ELM_SOFTWARE_WIN32) || - ENGINE_COMPARE(ELM_SOFTWARE_16_WINCE)) + ENGINE_COMPARE(ELM_SOFTWARE_16_WINCE) || + ENGINE_COMPARE(ELM_EWS)) #undef ENGINE_COMPARE evas_cserve_disconnect(); edje_shutdown(); diff --git a/src/lib/elm_priv.h b/src/lib/elm_priv.h index 6575ff0..b2866fe 100644 --- a/src/lib/elm_priv.h +++ b/src/lib/elm_priv.h @@ -80,6 +80,7 @@ extern const char *_elm_engines[]; #define ELM_SOFTWARE_16_SDL (_elm_engines[10]) #define ELM_OPENGL_SDL (_elm_engines[11]) #define ELM_BUFFER (_elm_engines[12]) +#define ELM_EWS (_elm_engines[13]) #define ELM_FONT_TOKEN_STYLE ":style=" @@ -167,6 +168,10 @@ struct _Elm_Module int references; }; +int _elm_ews_wm_init(void); +void _elm_ews_wm_shutdown(void); +void _elm_ews_wm_rescale(Elm_Theme *th, Eina_Bool use_theme); + void _elm_win_shutdown(void); void _elm_win_rescale(Elm_Theme *th, Eina_Bool use_theme); diff --git a/src/lib/elm_theme.c b/src/lib/elm_theme.c index 04642c4..9d123b4 100644 --- a/src/lib/elm_theme.c +++ b/src/lib/elm_theme.c @@ -570,6 +570,7 @@ elm_theme_flush(Elm_Theme *th) if (th->cache_data) eina_hash_free(th->cache_data); th->cache_data = eina_hash_string_superfast_new(EINA_FREE_CB(eina_stringshare_del)); _elm_win_rescale(th, EINA_TRUE); + _elm_ews_wm_rescale(th, EINA_TRUE); if (th->referrers) { Eina_List *l; diff --git a/src/lib/elm_win.c b/src/lib/elm_win.c index 337e231..aa00bd0 100644 --- a/src/lib/elm_win.c +++ b/src/lib/elm_win.c @@ -1479,6 +1479,10 @@ elm_win_add(Evas_Object *parent, const char *name, Elm_Win_Type type) { win->ee = ecore_evas_buffer_new(1, 1); } + else if (ENGINE_COMPARE(ELM_EWS)) + { + win->ee = ecore_evas_ews_new(0, 0, 1, 1); + } else if (!strncmp(_elm_config->engine, "shot:", 5)) { win->ee = ecore_evas_buffer_new(1, 1); diff --git a/src/lib/elu_ews_wm.c b/src/lib/elu_ews_wm.c new file mode 100644 index 0000000..de8fcfa --- /dev/null +++ b/src/lib/elu_ews_wm.c @@ -0,0 +1,542 @@ +#include +#include "elm_priv.h" + +static Eina_Bool _ews_used = EINA_FALSE; +static Eina_List *_ews_ev_handlers = NULL; +static Eina_Hash *_ews_borders = NULL; +static Eina_Hash *_ews_borders_geo = NULL; +static Evas_Object *_ews_bg = NULL; +static Ecore_Animator *_ews_border_mover = NULL; +static Evas_Object *_ews_border_mover_obj = NULL; +static Evas_Point _ews_border_mover_off = {0, 0}; + +static void +_elm_ews_border_usable_screen_geometry_get(int *x, int *y, int *w, int *h) +{ + Ecore_Evas *ee = ecore_evas_ews_ecore_evas_get(); + ecore_evas_geometry_get(ee, NULL, NULL, w, h); + if (x) *x = 0; + if (y) *y = 0; + // TODO: when add a shelf for iconified, subtract its area here. +} + +static void +_elm_ews_wm_border_del(void *data) +{ + Evas_Object *deco = data; + evas_object_del(deco); + + if (_ews_border_mover_obj == deco) + { + if (_ews_border_mover) + { + ecore_animator_del(_ews_border_mover); + _ews_border_mover = NULL; + } + _ews_border_mover_obj = NULL; + } +} + +static Evas_Object * +_elm_ews_wm_border_find(const Ecore_Evas *ee) +{ + return eina_hash_find(_ews_borders, &ee); +} + +static Eina_Rectangle * +_elm_ews_wm_border_geo_find(const Ecore_Evas *ee) +{ + return eina_hash_find(_ews_borders_geo, &ee); +} + +static void +_elm_ews_border_geo_apply(Ecore_Evas *ee, Evas_Object *o) +{ + int x, y, w, h; + ecore_evas_geometry_get(ee, &x, &y, &w, &h); + evas_object_move(o, x, y); + evas_object_resize(o, w, h); +} + +static void +_elm_ews_border_focus_apply(Ecore_Evas *ee, Evas_Object *o) +{ + const char *sig; + if (ecore_evas_focus_get(ee)) + sig = "elm,state,focus,on"; + else + sig = "elm,state,focus,off"; + edje_object_signal_emit(o, sig, "elm"); +} + +static void +_elm_ews_border_stack_apply(Ecore_Evas *ee, Evas_Object *o) +{ + Evas_Object *bs_o = ecore_evas_ews_backing_store_get(ee); + evas_object_stack_below(o, bs_o); +} + +static void +_elm_ews_border_iconified_apply(Ecore_Evas *ee, Evas_Object *o) +{ + const char *sig; + if (ecore_evas_iconified_get(ee)) + sig = "elm,state,iconified,on"; + else + sig = "elm,state,iconified,off"; + edje_object_signal_emit(o, sig, "elm"); + + // TODO: add to some taskbar? and actually hide it? + DBG("EWS does not implement iconified yet"); +} + +static void +_elm_ews_border_maximized_apply(Ecore_Evas *ee, Evas_Object *o) +{ + int x, y, w, h; + if (ecore_evas_maximized_get(ee)) + { + Eina_Rectangle *r; + int ex, ey, ew, eh; + + edje_object_signal_emit(o, "elm,state,maximized,on", "elm"); + edje_object_message_signal_process(o); + ecore_evas_geometry_get(ee, &x, &y, &w, &h); + + r = _elm_ews_wm_border_geo_find(ee); + if (!r) + { + r = malloc(sizeof(Eina_Rectangle)); + eina_hash_add(_ews_borders_geo, &ee, r); + } + + r->x = x; + r->y = y; + r->w = w; + r->h = h; + _elm_ews_border_usable_screen_geometry_get(&x, &y, &w, &h); + edje_object_parts_extends_calc(o, &ex, &ey, &ew, &eh); + x -= ex; + y -= ey; + w -= ew - r->w; + h -= eh - r->h; + } + else + { + Eina_Rectangle *r = _elm_ews_wm_border_geo_find(ee); + edje_object_signal_emit(o, "elm,state,maximized,off", "elm"); + + if (!r) ecore_evas_geometry_get(ee, &x, &y, &w, &h); + else + { + x = r->x; + y = r->y; + w = r->w; + h = r->h; + } + } + + ecore_evas_move_resize(ee, x, y, w, h); + _elm_ews_border_geo_apply(ee, o); +} + +static void +_elm_ews_border_layer_apply(Ecore_Evas *ee, Evas_Object *o) +{ + Evas_Object *bs_o = ecore_evas_ews_backing_store_get(ee); + evas_object_layer_set(o, evas_object_layer_get(bs_o)); + _elm_ews_border_stack_apply(ee, o); +} + +static void +_elm_ews_border_fullscreen_apply(Ecore_Evas *ee, Evas_Object *o) +{ + const char *sig; + if (ecore_evas_fullscreen_get(ee)) + sig = "elm,state,fullscreen,on"; + else + sig = "elm,state,fullscreen,off"; + edje_object_signal_emit(o, sig, "elm"); + _elm_ews_border_geo_apply(ee, o); +} + +static void +_elm_ews_border_config_apply(Ecore_Evas *ee, Evas_Object *o, Elm_Theme *th) +{ + const char *title, *name = NULL, *class = NULL, *style = NULL; + const char *sig; + + if (ecore_evas_borderless_get(ee)) + style = "borderless"; + + _elm_theme_set(th, o, "ews", "decoration", style ? style : "default"); + + if (ecore_evas_shaped_get(ee) || ecore_evas_alpha_get(ee) || + ecore_evas_transparent_get(ee)) + sig = "elm,state,alpha,on"; + else + sig = "elm,state,alpha,off"; + edje_object_signal_emit(o, sig, "elm"); + + title = ecore_evas_title_get(ee); + ecore_evas_name_class_get(ee, &name, &class); + edje_object_part_text_set(o, "elm.text.title", title); + edje_object_part_text_set(o, "elm.text.name", name); + edje_object_part_text_set(o, "elm.text.class", class); + + _elm_ews_border_geo_apply(ee, o); + _elm_ews_border_focus_apply(ee, o); + _elm_ews_border_stack_apply(ee, o); + _elm_ews_border_iconified_apply(ee, o); + _elm_ews_border_maximized_apply(ee, o); + _elm_ews_border_layer_apply(ee, o); + _elm_ews_border_fullscreen_apply(ee, o); +} + +static Eina_Bool +_elm_ews_wm_border_theme_set(Ecore_Evas *ee, Evas_Object *o, Elm_Theme *th) +{ + _elm_ews_border_config_apply(ee, o, th); + return EINA_TRUE; +} + +static void +_elm_ews_border_sig_focus(void *data, Evas_Object *o __UNUSED__, const char *sig __UNUSED__, const char *source __UNUSED__) +{ + Ecore_Evas *ee = data; + ecore_evas_focus_set(ee, EINA_TRUE); +} + +static void +_elm_ews_border_sig_iconify(void *data, Evas_Object *o __UNUSED__, const char *sig __UNUSED__, const char *source __UNUSED__) +{ + Ecore_Evas *ee = data; + ecore_evas_iconified_set(ee, EINA_TRUE); +} + +static void +_elm_ews_border_sig_maximize(void *data, Evas_Object *o __UNUSED__, const char *sig __UNUSED__, const char *source __UNUSED__) +{ + Ecore_Evas *ee = data; + ecore_evas_maximized_set(ee, EINA_TRUE); +} + +static void +_elm_ews_border_sig_fullscreen(void *data, Evas_Object *o __UNUSED__, const char *sig __UNUSED__, const char *source __UNUSED__) +{ + Ecore_Evas *ee = data; + ecore_evas_fullscreen_set(ee, EINA_TRUE); +} + +static void +_elm_ews_border_sig_restore(void *data, Evas_Object *o __UNUSED__, const char *sig __UNUSED__, const char *source __UNUSED__) +{ + Ecore_Evas *ee = data; + ecore_evas_iconified_set(ee, EINA_FALSE); + ecore_evas_maximized_set(ee, EINA_FALSE); + ecore_evas_fullscreen_set(ee, EINA_FALSE); +} + +static void +_elm_ews_border_sig_close(void *data, Evas_Object *o __UNUSED__, const char *sig __UNUSED__, const char *source __UNUSED__) +{ + Ecore_Evas *ee = data; + ecore_evas_ews_delete_request(ee); +} + +static void +_elm_ews_border_sig_menu(void *data, Evas_Object *o __UNUSED__, const char *sig __UNUSED__, const char *source __UNUSED__) +{ + // TODO: show some menu? + ERR("EWS does not implement menu yet"); + (void)data; +} + +static Eina_Bool +_elm_ews_border_mover(void *data) +{ + Ecore_Evas *ee = data; + Evas_Object *o = _elm_ews_wm_border_find(ee); + int x, y; + + evas_pointer_output_xy_get(ecore_evas_ews_evas_get(), &x, &y); + x -= _ews_border_mover_off.x; + y -= _ews_border_mover_off.y; + ecore_evas_move(ee, x, y); + evas_object_move(o, x, y); + + return EINA_TRUE; +} + +static void +_elm_ews_border_sig_move_start(void *data, Evas_Object *o __UNUSED__, const char *sig __UNUSED__, const char *source __UNUSED__) +{ + Ecore_Evas *ee = data; + Evas_Object *bs_o = ecore_evas_ews_backing_store_get(ee); + int x, y, ox, oy; + + if (_ews_border_mover) ecore_animator_del(_ews_border_mover); + + evas_pointer_output_xy_get(evas_object_evas_get(bs_o), &x, &y); + evas_object_geometry_get(bs_o, &ox, &oy, NULL, NULL); + _ews_border_mover_off.x = x - ox; + _ews_border_mover_off.y = y - oy; + _ews_border_mover_obj = bs_o; + _ews_border_mover = ecore_animator_add(_elm_ews_border_mover, ee); +} + +static void +_elm_ews_border_sig_move_stop(void *data __UNUSED__, Evas_Object *o __UNUSED__, const char *sig __UNUSED__, const char *source __UNUSED__) +{ + if (!_ews_border_mover) return; + ecore_animator_del(_ews_border_mover); + _ews_border_mover = NULL; + _ews_border_mover_obj = NULL; +} + +static Eina_Bool +_elm_ews_wm_add_cb(void *data __UNUSED__, int type __UNUSED__, void *event_info) +{ + Ecore_Evas *ee = event_info; + Evas_Object *o = edje_object_add(ecore_evas_ews_evas_get()); + Evas_Coord x, y, w, h, sw, sh; + + edje_object_signal_callback_add + (o, "elm,action,focus", "elm", _elm_ews_border_sig_focus, ee); + edje_object_signal_callback_add + (o, "elm,action,iconify", "elm", _elm_ews_border_sig_iconify, ee); + edje_object_signal_callback_add + (o, "elm,action,maximize", "elm", _elm_ews_border_sig_maximize, ee); + edje_object_signal_callback_add + (o, "elm,action,fullscreen", "elm", _elm_ews_border_sig_fullscreen, ee); + edje_object_signal_callback_add + (o, "elm,action,restore", "elm", _elm_ews_border_sig_restore, ee); + edje_object_signal_callback_add + (o, "elm,action,close", "elm", _elm_ews_border_sig_close, ee); + edje_object_signal_callback_add + (o, "elm,action,menu", "elm", _elm_ews_border_sig_menu, ee); + edje_object_signal_callback_add + (o, "elm,action,move,start", "elm", _elm_ews_border_sig_move_start, ee); + edje_object_signal_callback_add + (o, "elm,action,move,stop", "elm", _elm_ews_border_sig_move_stop, ee); + + eina_hash_add(_ews_borders, &ee, o); + _elm_ews_wm_border_theme_set(ee, o, NULL); + + ecore_evas_screen_geometry_get(ee, NULL, NULL, &sw, &sh); + ecore_evas_geometry_get(ee, NULL, NULL, &w, &h); + x = (sw - w) / 2; + y = (sh - h) / 2; + ecore_evas_move(ee, x, y); + + return EINA_TRUE; +} + +static Eina_Bool +_elm_ews_wm_del_cb(void *data __UNUSED__, int type __UNUSED__, void *event_info) +{ + Ecore_Evas *ee = event_info; + eina_hash_del(_ews_borders, &ee, NULL); + eina_hash_del(_ews_borders_geo, &ee, NULL); + return EINA_TRUE; +} + +static Eina_Bool +_elm_ews_wm_geo_cb(void *data __UNUSED__, int type __UNUSED__, void *event_info) +{ + Ecore_Evas *ee = event_info; + Evas_Object *o = _elm_ews_wm_border_find(ee); + _elm_ews_border_geo_apply(ee, o); + return EINA_TRUE; +} + +static Eina_Bool +_elm_ews_wm_show_cb(void *data __UNUSED__, int type __UNUSED__, void *event_info) +{ + Ecore_Evas *ee = event_info; + Evas_Object *o = _elm_ews_wm_border_find(ee); + evas_object_show(o); + return EINA_TRUE; +} + +static Eina_Bool +_elm_ews_wm_hide_cb(void *data __UNUSED__, int type __UNUSED__, void *event_info) +{ + Ecore_Evas *ee = event_info; + Evas_Object *o = _elm_ews_wm_border_find(ee); + evas_object_hide(o); + return EINA_TRUE; +} + +static Eina_Bool +_elm_ews_wm_focus_cb(void *data __UNUSED__, int type __UNUSED__, void *event_info) +{ + Ecore_Evas *ee = event_info; + Evas_Object *o = _elm_ews_wm_border_find(ee); + _elm_ews_border_focus_apply(ee, o); + return EINA_TRUE; +} + +static Eina_Bool +_elm_ews_wm_stack_cb(void *data __UNUSED__, int type __UNUSED__, void *event_info) +{ + Ecore_Evas *ee = event_info; + Evas_Object *o = _elm_ews_wm_border_find(ee); + _elm_ews_border_stack_apply(ee, o); + return EINA_TRUE; +} + +static Eina_Bool +_elm_ews_wm_iconified_change_cb(void *data __UNUSED__, int type __UNUSED__, void *event_info) +{ + Ecore_Evas *ee = event_info; + Evas_Object *o = _elm_ews_wm_border_find(ee); + _elm_ews_border_iconified_apply(ee, o); + return EINA_TRUE; +} + +static Eina_Bool +_elm_ews_wm_maximized_change_cb(void *data __UNUSED__, int type __UNUSED__, void *event_info) +{ + Ecore_Evas *ee = event_info; + Evas_Object *o = _elm_ews_wm_border_find(ee); + _elm_ews_border_maximized_apply(ee, o); + return EINA_TRUE; +} + +static Eina_Bool +_elm_ews_wm_layer_change_cb(void *data __UNUSED__, int type __UNUSED__, void *event_info) +{ + Ecore_Evas *ee = event_info; + Evas_Object *o = _elm_ews_wm_border_find(ee); + _elm_ews_border_layer_apply(ee, o); + return EINA_TRUE; +} + +static Eina_Bool +_elm_ews_wm_fullscreen_change_cb(void *data __UNUSED__, int type __UNUSED__, void *event_info) +{ + Ecore_Evas *ee = event_info; + Evas_Object *o = _elm_ews_wm_border_find(ee); + _elm_ews_border_fullscreen_apply(ee, o); + return EINA_TRUE; +} + +static Eina_Bool +_elm_ews_wm_config_change_cb(void *data __UNUSED__, int type __UNUSED__, void *event_info) +{ + Ecore_Evas *ee = event_info; + Evas_Object *o = _elm_ews_wm_border_find(ee); + _elm_ews_border_config_apply(ee, o, NULL); + return EINA_TRUE; +} + +void +_elm_ews_wm_rescale(Elm_Theme *th, Eina_Bool use_theme) +{ + Eina_Iterator *it = eina_hash_iterator_tuple_new(_ews_borders); + Eina_Hash_Tuple *tp = NULL; + + if (!use_theme) + { + EINA_ITERATOR_FOREACH(it, tp) + _elm_ews_wm_border_theme_set((void*)tp->key, tp->data, NULL); + + if (_ews_bg) + _elm_theme_set(NULL, _ews_bg, "ews", "background", "default"); + } + else + { + EINA_ITERATOR_FOREACH(it, tp) + _elm_ews_wm_border_theme_set((void*)tp->key, tp->data, th); + + if (_ews_bg) + _elm_theme_set(th, _ews_bg, "ews", "background", "default"); + } + + eina_iterator_free(it); +} + +int +_elm_ews_wm_init(void) +{ + Evas *e; + Evas_Object *o; + + if (strcmp(_elm_config->engine, ELM_EWS) != 0) + { + _ews_used = EINA_FALSE; + return EINA_TRUE; + } + + e = ecore_evas_ews_evas_get(); + if (!e) return EINA_FALSE; + o = edje_object_add(e); + if (!o) return EINA_FALSE; + + if (!_elm_theme_set(NULL, o, "ews", "background", "default")) + { + ERR("Could not set background theme, fallback to rectangle"); + evas_object_del(o); + _ews_bg = o = NULL; + } + else + _ews_bg = o; + ecore_evas_ews_background_set(o); + + +#define ADD_EH(ev, cb) \ + _ews_ev_handlers = eina_list_append \ + (_ews_ev_handlers, ecore_event_handler_add(ev, cb, NULL)) + ADD_EH(ECORE_EVAS_EWS_EVENT_ADD, _elm_ews_wm_add_cb); + ADD_EH(ECORE_EVAS_EWS_EVENT_DEL, _elm_ews_wm_del_cb); + ADD_EH(ECORE_EVAS_EWS_EVENT_RESIZE, _elm_ews_wm_geo_cb); + ADD_EH(ECORE_EVAS_EWS_EVENT_MOVE, _elm_ews_wm_geo_cb); + ADD_EH(ECORE_EVAS_EWS_EVENT_SHOW, _elm_ews_wm_show_cb); + ADD_EH(ECORE_EVAS_EWS_EVENT_HIDE, _elm_ews_wm_hide_cb); + ADD_EH(ECORE_EVAS_EWS_EVENT_FOCUS, _elm_ews_wm_focus_cb); + ADD_EH(ECORE_EVAS_EWS_EVENT_UNFOCUS, _elm_ews_wm_focus_cb); + ADD_EH(ECORE_EVAS_EWS_EVENT_RAISE, _elm_ews_wm_stack_cb); + ADD_EH(ECORE_EVAS_EWS_EVENT_LOWER, _elm_ews_wm_stack_cb); + ADD_EH(ECORE_EVAS_EWS_EVENT_ICONIFIED_CHANGE, _elm_ews_wm_iconified_change_cb); + ADD_EH(ECORE_EVAS_EWS_EVENT_MAXIMIZED_CHANGE, _elm_ews_wm_maximized_change_cb); + ADD_EH(ECORE_EVAS_EWS_EVENT_LAYER_CHANGE, _elm_ews_wm_layer_change_cb); + ADD_EH(ECORE_EVAS_EWS_EVENT_FULLSCREEN_CHANGE, _elm_ews_wm_fullscreen_change_cb); + ADD_EH(ECORE_EVAS_EWS_EVENT_CONFIG_CHANGE, _elm_ews_wm_config_change_cb); +#undef ADD_EH + + if (!_ews_borders) + _ews_borders = eina_hash_pointer_new(_elm_ews_wm_border_del); + + if (!_ews_borders_geo) + _ews_borders_geo = eina_hash_pointer_new(free); + + _ews_used = EINA_TRUE; + return EINA_TRUE; +} + +void +_elm_ews_wm_shutdown(void) +{ + Ecore_Event_Handler *eh; + + if (_ews_border_mover) + { + ecore_animator_del(_ews_border_mover); + _ews_border_mover = NULL; + } + _ews_border_mover_obj = NULL; + + EINA_LIST_FREE(_ews_ev_handlers, eh) ecore_event_handler_del(eh); + if (_ews_borders) + { + eina_hash_free(_ews_borders); + _ews_borders = NULL; + } + if (_ews_borders_geo) + { + eina_hash_free(_ews_borders_geo); + _ews_borders_geo = NULL; + } + _ews_bg = NULL; +}