diff --git a/data/themes/default.edc b/data/themes/default.edc index 9221890f..c9d4c9a6 100644 --- a/data/themes/default.edc +++ b/data/themes/default.edc @@ -12,6 +12,9 @@ collections { image: "bg_led_base.png" COMP; image: "bg_led.png" COMP; image: "bg_led_strobe.png" COMP; + image: "pm_shadow.png" COMP; + image: "pm_overlay.png" COMP; + image: "pm_fill.png" COMP; } parts { // other signals sent not handled here @@ -320,6 +323,317 @@ collections { target: "bell_strobe"; } + //////////////////////////////////////////////////////////////////// + // popup media over the terminal (until dismissed) + part { name: "popmedia_clip"; type: RECT; + mouse_events: 1; + description { state: "default" 0.0; + fixed: 1 1; + visible: 0; + color: 255 255 255 0; + } + description { state: "visible" 0.0; + inherit: "default" 0.0; + visible: 1; + color: 255 255 255 255; + } + } + part { name: "popmedia_shadow"; + mouse_events: 0; + description { state: "default" 0.0; + fixed: 1 1; + rel1 { + to: "terminology.popmedia"; + } + rel2 { + to: "terminology.popmedia"; + } + image.normal: "pm_shadow.png"; + image.border: 64 64 64 64; + image.border_scale_by: 0.1; + fill.smooth: 0; + visible: 0; + } + description { state: "visible" 0.0; + inherit: "default" 0.0; + rel1.offset: -32 -32; + rel2.offset: 31 31; + image.border_scale_by: 1.0; + visible: 1; + } + } + part { name: "popmedia_fill"; + mouse_events: 0; + description { state: "default" 0.0; + fixed: 1 1; + rel1.to: "terminology.popmedia"; + rel2.to: "terminology.popmedia"; + image.normal: "pm_fill.png"; + fill { + size.relative: 0.0 0.0; + size.offset: 64 64; + } + } + } + part { name: "terminology.popmedia"; type: SWALLOW; + clip_to: "popmedia_clip"; + description { state: "default" 0.0; + fixed: 1 1; + rel1.relative: 0.5 0.5; + rel2.relative: 0.5 0.5; + visible: 0; + } + description { state: "image" 0.0; + inherit: "default" 0.0; + rel1.relative: 0.1 0.1; + rel2.relative: 0.9 0.9; + visible: 1; + } + description { state: "scale" 0.0; + inherit: "default" 0.0; + rel1.relative: 0.1 0.1; + rel2.relative: 0.9 0.9; + visible: 1; + } + description { state: "edje" 0.0; + inherit: "default" 0.0; + rel1.relative: 0.1 0.1; + rel2.relative: 0.9 0.9; + visible: 1; + } + description { state: "movie" 0.0; + inherit: "default" 0.0; + rel1.relative: 0.1 0.1; + rel2.relative: 0.9 0.9; + visible: 1; + } + } + part { name: "popmedia_overlay"; + mouse_events: 0; + description { state: "default" 0.0; + fixed: 1 1; + rel1.to: "terminology.popmedia"; + rel2.to: "terminology.popmedia"; + image.normal: "pm_overlay.png"; + fill.smooth: 0; + visible: 0; + } + description { state: "visible" 0.0; + inherit: "default" 0.0; + visible: 1; + } + } + part { name: "popmedia_bevel"; + mouse_events: 0; + description { state: "default" 0.0; + fixed: 1 1; + rel1.to: "terminology.popmedia"; + rel2.to: "terminology.popmedia"; + image.normal: "bg_bevel.png"; + image.border: 3 3 5 3; + image.middle: 0; + fill.smooth: 0; + visible: 0; + } + description { state: "visible" 0.0; + inherit: "default" 0.0; + visible: 1; + } + } + part { name: "popmedia_glintclip"; type: RECT; + mouse_events: 0; + description { state: "default" 0.0; + fixed: 1 1; + visible: 0; + } + description { state: "visible" 0.0; + inherit: "default" 0.0; + visible: 1; + } + } + part { name: "popmedia_glint"; + mouse_events: 0; + clip_to: "popmedia_glintclip"; + description { state: "default" 0.0; + fixed: 1 1; + min: 79 5; + max: 79 5; + rel1 { + to: "terminology.popmedia"; + relative: 0.0 0.0; + offset: 0 0; + } + rel2 { + to: "terminology.popmedia"; + relative: 1.0 0.0; + offset: -1 0; + } + image.normal: "bg_glint.png"; + visible: 0; + } + description { state: "visible" 0.0; + inherit: "default" 0.0; + visible: 1; + } + } + part { name: "popmedia_shine"; + mouse_events: 0; + description { state: "default" 0.0; + fixed: 1 1; + rel1.to: "terminology.popmedia"; + rel2.to: "terminology.popmedia"; + image.normal: "bg_shine.png"; + fill.smooth: 0; + align: 0.5 0.0; + aspect: (255/120) (255/120); + aspect_preference: HORIZONTAL; + visible: 0; + } + description { state: "visible" 0.0; + inherit: "default" 0.0; + visible: 1; + } + } + part { name: "popmedia_dismiss"; type: RECT; + mouse_events: 1; + description { state: "default" 0.0; + fixed: 1 1; + color: 0 0 0 0; + visible: 0; + rel1.to: "terminology.popmedia"; + rel2.to: "terminology.popmedia"; + } + description { state: "visible" 0.0; + inherit: "default" 0.0; + visible: 1; + } + } + program { name: "popmedia_dismiss"; + signal: "mouse,clicked,*"; + source: "popmedia_dismiss"; + action: STATE_SET "default" 0.0; + transition: DECELERATE 0.5; + target: "terminology.popmedia"; + target: "popmedia_clip"; + target: "popmedia_dismiss"; + target: "popmedia_shadow"; + target: "popmedia_fill"; + target: "popmedia_overlay"; + target: "popmedia_bevel"; + target: "popmedia_glint"; + target: "popmedia_glintclip"; + target: "popmedia_shine"; + after: "popmedia_dismiss2"; + } + program { name: "popmedia_dismiss2"; + action: SIGNAL_EMIT "popmedia,done" "terminology"; + } + program { name: "popmedia_off"; + signal: "popmedia,off"; + source: "terminology"; + action: STATE_SET "default" 0.0; + transition: DECELERATE 0.2; + target: "terminology.popmedia"; + target: "popmedia_clip"; + target: "popmedia_dismiss"; + target: "popmedia_shadow"; + target: "popmedia_fill"; + target: "popmedia_overlay"; + target: "popmedia_bevel"; + target: "popmedia_glint"; + target: "popmedia_glintclip"; + target: "popmedia_shine"; + after: "popmedia_dismiss2"; + } + program { name: "popmedia_img"; + signal: "popmedia,image"; + source: "terminology"; + action: STATE_SET "image" 0.0; + transition: DECELERATE 0.2; + target: "terminology.popmedia"; + } + program { name: "popmedia_scale"; + signal: "popmedia,scale"; + source: "terminology"; + action: STATE_SET "scale" 0.0; + transition: DECELERATE 0.2; + target: "terminology.popmedia"; + } + program { name: "popmedia_edje"; + signal: "popmedia,edje"; + source: "terminology"; + action: STATE_SET "edje" 0.0; + transition: DECELERATE 0.2; + target: "terminology.popmedia"; + } + program { name: "popmedia_mov"; + signal: "popmedia,movie"; + source: "terminology"; + action: STATE_SET "movie" 0.0; + transition: DECELERATE 0.2; + target: "terminology.popmedia"; + } + program { name: "popmedia_img2"; + signal: "popmedia,image"; + source: "terminology"; + action: STATE_SET "visible" 0.0; + transition: DECELERATE 0.2; + target: "popmedia_clip"; + target: "popmedia_dismiss"; + target: "popmedia_shadow"; + target: "popmedia_fill"; + target: "popmedia_overlay"; + target: "popmedia_bevel"; + target: "popmedia_glint"; + target: "popmedia_glintclip"; + target: "popmedia_shine"; + } + program { name: "popmedia_scale2"; + signal: "popmedia,scale"; + source: "terminology"; + action: STATE_SET "visible" 0.0; + transition: DECELERATE 0.2; + target: "popmedia_clip"; + target: "popmedia_dismiss"; + target: "popmedia_shadow"; + target: "popmedia_fill"; + target: "popmedia_overlay"; + target: "popmedia_bevel"; + target: "popmedia_glint"; + target: "popmedia_glintclip"; + target: "popmedia_shine"; + } + program { name: "popmedia_edje2"; + signal: "popmedia,edje"; + source: "terminology"; + action: STATE_SET "visible" 0.0; + transition: DECELERATE 0.2; + target: "popmedia_clip"; + target: "popmedia_dismiss"; + target: "popmedia_shadow"; + target: "popmedia_fill"; + target: "popmedia_overlay"; + target: "popmedia_bevel"; + target: "popmedia_glint"; + target: "popmedia_glintclip"; + target: "popmedia_shine"; + } + program { name: "popmedia_mov2"; + signal: "popmedia,movie"; + source: "terminology"; + action: STATE_SET "visible" 0.0; + transition: DECELERATE 0.2; + target: "popmedia_clip"; + target: "popmedia_dismiss"; + target: "popmedia_shadow"; + target: "popmedia_fill"; + target: "popmedia_overlay"; + target: "popmedia_bevel"; + target: "popmedia_glint"; + target: "popmedia_glintclip"; + target: "popmedia_shine"; + } + //////////////////////////////////////////////////////////////////// // overlayed options and controls part { name: "terminology.about"; type: SWALLOW; @@ -630,6 +944,118 @@ collections { } } +////////////////////////////////////////////////////////////////////////////// + //// an object overlayd on text that is a link + group { name: "terminology/link"; + images { + image: "lk_bottom.png" COMP; + image: "lk_left.png" COMP; + image: "lk_right.png" COMP; + } + parts { + part { name: "bottom"; + mouse_events: 0; + description { state: "default" 0.0; + image.normal: "lk_bottom.png"; + image.border: 9 9 0 0; + align: 0.5 1.0; + min: 20 8; + rel1.offset: -6 0; + rel1.relative: 0.0 1.0; + rel2.offset: 5 0; + color: 100 200 255 255; + fill.smooth: 0; + } + } + part { name: "l"; + mouse_events: 0; + description { state: "default" 0.0; + image.normal: "lk_left.png"; + align: 0.0 1.0; + min: 4 4; + rel1.offset: 16 -1; + rel1.relative: 0.0 1.0; + rel2.offset: 16 -1; + rel2.relative: 0.0 1.0; + color: 100 200 255 0; + } + description { state: "out" 0.0; + inherit: "default" 0.0; + min: 16 16; + rel1.offset: -10 -1; + rel2.offset: -10 -1; + color: 180 220 255 255; + } + description { state: "out2" 0.0; + inherit: "default" 0.0; + min: 32 32; + rel1.offset: -26 -1; + rel2.offset: -26 -1; + color: 100 200 255 0; + } + } + part { name: "r"; + mouse_events: 0; + description { state: "default" 0.0; + image.normal: "lk_right.png"; + align: 1.0 1.0; + min: 4 4; + rel1.offset: -15 0; + rel1.relative: 1.0 1.0; + rel2.offset: -15 0; + rel2.relative: 1.0 1.0; + color: 100 200 255 0; + } + description { state: "out" 0.0; + inherit: "default" 0.0; + min: 16 16; + rel1.offset: 9 -1; + rel2.offset: 9 -1; + color: 180 220 255 255; + } + description { state: "out2" 0.0; + inherit: "default" 0.0; + min: 32 32; + rel1.offset: 25 -1; + rel2.offset: 25 -1; + color: 100 200 255 0; + } + } + part { name: "event"; type: RECT; + mouse_events: 1; + repeat_events: 1; + description { state: "default" 0.0; + color: 0 0 0 0; + } + } + programs { + program { name: "show"; + signal: "show"; + source: ""; + action: STATE_SET "out" 0.0; + transition: LINEAR 0.3; + target: "l"; + target: "r"; + after: "show2"; + } + program { name: "show2"; + action: STATE_SET "default" 0.0; + action: STATE_SET "out2" 0.0; + transition: LINEAR 0.3; + target: "l"; + target: "r"; + after: "show3"; + } + program { name: "show3"; + action: STATE_SET "default" 0.0; + target: "l"; + target: "r"; + after: "show"; + } + } + } + } + ////////////////////////////////////////////////////////////////////////////// //// the multimedia controls group { name: "terminology/mediactrl"; diff --git a/data/themes/images/Makefile.am b/data/themes/images/Makefile.am index 86d3d0f1..4491429d 100644 --- a/data/themes/images/Makefile.am +++ b/data/themes/images/Makefile.am @@ -21,4 +21,10 @@ media_pause.png \ media_play.png \ media_stop.png \ media_knob_pos.png \ -media_knob_vol.png +media_knob_vol.png \ +pm_fill.png \ +pm_overlay.png \ +pm_shadow.png \ +lk_bottom.png \ +lk_left.png \ +lk_right.png diff --git a/data/themes/images/lk_bottom.png b/data/themes/images/lk_bottom.png new file mode 100644 index 00000000..7b7007de Binary files /dev/null and b/data/themes/images/lk_bottom.png differ diff --git a/data/themes/images/lk_left.png b/data/themes/images/lk_left.png new file mode 100644 index 00000000..3db09dcd Binary files /dev/null and b/data/themes/images/lk_left.png differ diff --git a/data/themes/images/lk_right.png b/data/themes/images/lk_right.png new file mode 100644 index 00000000..715bdc36 Binary files /dev/null and b/data/themes/images/lk_right.png differ diff --git a/data/themes/images/pm_fill.png b/data/themes/images/pm_fill.png new file mode 100644 index 00000000..8ef098f1 Binary files /dev/null and b/data/themes/images/pm_fill.png differ diff --git a/data/themes/images/pm_overlay.png b/data/themes/images/pm_overlay.png new file mode 100644 index 00000000..3c25c730 Binary files /dev/null and b/data/themes/images/pm_overlay.png differ diff --git a/data/themes/images/pm_shadow.png b/data/themes/images/pm_shadow.png new file mode 100644 index 00000000..cde4f73b Binary files /dev/null and b/data/themes/images/pm_shadow.png differ diff --git a/src/bin/Makefile.am b/src/bin/Makefile.am index 8aedb06d..2bb6c90c 100644 --- a/src/bin/Makefile.am +++ b/src/bin/Makefile.am @@ -19,6 +19,7 @@ main.c main.h \ media.c media.h \ options.c options.h \ options_behavior.c options_behavior.h \ +options_helpers.c options_helpers.h \ options_font.c options_font.h \ options_video.c options_video.h \ options_theme.c options_theme.h \ diff --git a/src/bin/config.c b/src/bin/config.c index 8a51b185..ef8dc5b5 100644 --- a/src/bin/config.c +++ b/src/bin/config.c @@ -48,6 +48,22 @@ config_init(void) (edd_base, Config, "font.size", font.size, EET_T_INT); EET_DATA_DESCRIPTOR_ADD_BASIC (edd_base, Config, "font.bitmap", font.bitmap, EET_T_UCHAR); + EET_DATA_DESCRIPTOR_ADD_BASIC + (edd_base, Config, "helper.email", helper.email, EET_T_STRING); + EET_DATA_DESCRIPTOR_ADD_BASIC + (edd_base, Config, "helper.url.general", helper.url.general, EET_T_STRING); + EET_DATA_DESCRIPTOR_ADD_BASIC + (edd_base, Config, "helper.url.video", helper.url.video, EET_T_STRING); + EET_DATA_DESCRIPTOR_ADD_BASIC + (edd_base, Config, "helper.url.image", helper.url.image, EET_T_STRING); + EET_DATA_DESCRIPTOR_ADD_BASIC + (edd_base, Config, "helper.local.general", helper.local.general, EET_T_STRING); + EET_DATA_DESCRIPTOR_ADD_BASIC + (edd_base, Config, "helper.local.video", helper.local.video, EET_T_STRING); + EET_DATA_DESCRIPTOR_ADD_BASIC + (edd_base, Config, "helper.local.image", helper.local.image, EET_T_STRING); + EET_DATA_DESCRIPTOR_ADD_BASIC + (edd_base, Config, "helper.inline_please", helper.inline_please, EET_T_UCHAR); EET_DATA_DESCRIPTOR_ADD_BASIC (edd_base, Config, "theme", theme, EET_T_STRING); EET_DATA_DESCRIPTOR_ADD_BASIC @@ -192,6 +208,14 @@ config_load(const char *key) config->font.bitmap = EINA_TRUE; config->font.name = eina_stringshare_add("nexus.pcf"); config->font.size = 10; + config->helper.email = eina_stringshare_add("xdg-email");; + config->helper.url.general = eina_stringshare_add("xdg-open"); + config->helper.url.video = eina_stringshare_add("xdg-open"); + config->helper.url.image = eina_stringshare_add("xdg-open"); + config->helper.local.general = eina_stringshare_add("xdg-open"); + config->helper.local.video = eina_stringshare_add("xdg-open"); + config->helper.local.image = eina_stringshare_add("xdg-open"); + config->helper.inline_please = EINA_TRUE; config->scrollback = 2000; config->theme = eina_stringshare_add("default.edj"); config->background = NULL; diff --git a/src/bin/config.h b/src/bin/config.h index e54f1f43..9bb2068c 100644 --- a/src/bin/config.h +++ b/src/bin/config.h @@ -12,6 +12,15 @@ struct _Config int size; unsigned char bitmap; } font; + struct { + const char *email; + struct { + const char *general; + const char *video; + const char *image; + } url, local; + Eina_Bool inline_please; + } helper; const char *theme; const char *background; const char *wordsep; diff --git a/src/bin/main.c b/src/bin/main.c index c7ce5dbd..92a79c97 100644 --- a/src/bin/main.c +++ b/src/bin/main.c @@ -13,6 +13,7 @@ int _log_domain = -1; static Evas_Object *win = NULL, *bg = NULL, *term = NULL, *media = NULL; +static Evas_Object *popmedia = NULL; static Evas_Object *conform = NULL; static Ecore_Timer *flush_timer = NULL; static Eina_Bool focused = EINA_FALSE; @@ -94,6 +95,43 @@ _cb_bell(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event __UNUSE } } +static void +_cb_popmedia_done(void *data __UNUSED__, Evas_Object *obj __UNUSED__, const char *sig __UNUSED__, const char *src __UNUSED__) +{ + if (popmedia) + { + evas_object_del(popmedia); + popmedia = NULL; + termio_mouseover_suspend_pushpop(term, -1); + } +} + +static void +_cb_popup(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event __UNUSED__) +{ + Evas_Object *o; + Config *config = termio_config_get(term); + const char *src; + int type = 0; + + if (!config) return; + src = termio_link_get(term); + if (!src) return; + if (popmedia) evas_object_del(popmedia); + if (!popmedia) termio_mouseover_suspend_pushpop(term, 1); + popmedia = o = media_add(win, src, config, MEDIA_POP, &type); + edje_object_part_swallow(bg, "terminology.popmedia", o); + evas_object_show(o); + if (type == TYPE_IMG) + edje_object_signal_emit(bg, "popmedia,image", "terminology"); + else if (type == TYPE_SCALE) + edje_object_signal_emit(bg, "popmedia,scale", "terminology"); + else if (type == TYPE_EDJE) + edje_object_signal_emit(bg, "popmedia,edje", "terminology"); + else if (type == TYPE_MOV) + edje_object_signal_emit(bg, "popmedia,movie", "terminology"); +} + void main_trans_update(const Config *config) { @@ -120,6 +158,7 @@ main_media_update(const Config *config) if (media) evas_object_del(media); o = media = media_add(win, config->background, config, MEDIA_BG, &type); edje_object_part_swallow(bg, "terminology.background", o); + evas_object_show(o); if (type == TYPE_IMG) edje_object_signal_emit(bg, "media,image", "terminology"); else if (type == TYPE_SCALE) @@ -128,7 +167,6 @@ main_media_update(const Config *config) edje_object_signal_emit(bg, "media,edje", "terminology"); else if (type == TYPE_MOV) edje_object_signal_emit(bg, "media,movie", "terminology"); - evas_object_show(o); } else { @@ -378,6 +416,9 @@ elm_main(int argc, char **argv) theme_auto_reload_enable(o); elm_object_content_set(conform, o); evas_object_show(o); + + edje_object_signal_callback_add(o, "popmedia,done", "terminology", + _cb_popmedia_done, NULL); if (pos_set) { @@ -399,6 +440,7 @@ elm_main(int argc, char **argv) evas_object_smart_callback_add(o, "change", _cb_change, NULL); evas_object_smart_callback_add(o, "exited", _cb_exited, NULL); evas_object_smart_callback_add(o, "bell", _cb_bell, NULL); + evas_object_smart_callback_add(o, "popup", _cb_popup, NULL); evas_object_show(o); main_trans_update(config); diff --git a/src/bin/media.c b/src/bin/media.c index d9e87500..30277dd1 100644 --- a/src/bin/media.c +++ b/src/bin/media.c @@ -143,13 +143,32 @@ _type_img_calc(Evas_Object *obj, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_ { int iw, ih; - iw = w; - ih = (sd->ih * w) / sd->iw; - if (ih < h) + if (sd->mode == MEDIA_BG) { - ih = h; - iw = (sd->iw * h) / sd->ih; - if (iw < w) iw = w; + iw = w; + ih = (sd->ih * w) / sd->iw; + if (ih < h) + { + ih = h; + iw = (sd->iw * h) / sd->ih; + if (iw < w) iw = w; + } + } + else if (sd->mode == MEDIA_POP) + { + iw = w; + ih = (sd->ih * w) / sd->iw; + if (ih > h) + { + ih = h; + iw = (sd->iw * h) / sd->ih; + if (iw > w) iw = w; + } + if ((iw > sd->iw) || (ih > sd->ih)) + { + iw = sd->iw; + ih = sd->ih; + } } x += ((w - iw) / 2); y += ((h - ih) / 2); @@ -208,13 +227,27 @@ _type_scale_calc(Evas_Object *obj, Evas_Coord x, Evas_Coord y, Evas_Coord w, Eva { int iw, ih; - iw = w; - ih = (sd->ih * w) / sd->iw; - if (ih < h) + if (sd->mode == MEDIA_BG) { - ih = h; - iw = (sd->iw * h) / sd->ih; - if (iw < w) iw = w; + iw = w; + ih = (sd->ih * w) / sd->iw; + if (ih < h) + { + ih = h; + iw = (sd->iw * h) / sd->ih; + if (iw < w) iw = w; + } + } + else if (sd->mode == MEDIA_POP) + { + iw = w; + ih = (sd->ih * w) / sd->iw; + if (ih > h) + { + ih = h; + iw = (sd->iw * h) / sd->ih; + if (iw > w) iw = w; + } } x += ((w - iw) / 2); y += ((h - ih) / 2); @@ -502,14 +535,28 @@ _type_mov_calc(Evas_Object *obj, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_ ratio = emotion_object_ratio_get(sd->o_img); if (ratio > 0.0) sd->iw = (sd->ih * ratio) + 0.5; else ratio = (double)sd->iw / (double)sd->ih; - - iw = w; - ih = w / ratio; - if (ih < h) + + if (sd->mode == MEDIA_BG) { - ih = h; - iw = h * ratio; - if (iw < w) iw = w; + iw = w; + ih = w / ratio; + if (ih < h) + { + ih = h; + iw = h * ratio; + if (iw < w) iw = w; + } + } + else if (sd->mode == MEDIA_POP) + { + iw = w; + ih = w / ratio; + if (ih > h) + { + ih = h; + iw = h * ratio; + if (iw > w) iw = w; + } } x += ((w - iw) / 2); y += ((h - ih) / 2); @@ -706,3 +753,15 @@ media_volume_set(Evas_Object *obj, double vol) emotion_object_audio_volume_set(sd->o_img, vol); edje_object_part_drag_value_set(sd->o_ctrl, "terminology.voldrag", vol, vol); } + +int +media_src_type_get(const char *src) +{ + int type = TYPE_UNKNOWN; + + if (_is_fmt(src, extn_img)) type = TYPE_IMG; + else if (_is_fmt(src, extn_scale)) type = TYPE_SCALE; + else if (_is_fmt(src, extn_edj)) type = TYPE_EDJE; + else if (_is_fmt(src, extn_mov)) type = TYPE_MOV; + return type; +} diff --git a/src/bin/media.h b/src/bin/media.h index 1aa8779a..8d99e93b 100644 --- a/src/bin/media.h +++ b/src/bin/media.h @@ -2,11 +2,13 @@ #define _MEDIA_H__ 1 #define MEDIA_BG 0 +#define MEDIA_POP 1 -#define TYPE_IMG 0 -#define TYPE_SCALE 1 -#define TYPE_EDJE 2 -#define TYPE_MOV 3 +#define TYPE_UNKNOWN -1 +#define TYPE_IMG 0 +#define TYPE_SCALE 1 +#define TYPE_EDJE 2 +#define TYPE_MOV 3 #include "config.h" @@ -16,5 +18,6 @@ void media_play_set(Evas_Object *obj, Eina_Bool play); void media_position_set(Evas_Object *obj, double pos); void media_volume_set(Evas_Object *obj, double vol); void media_stop(Evas_Object *obj); +int media_src_type_get(const char *src); #endif diff --git a/src/bin/options.c b/src/bin/options.c index 67332663..c58bdeca 100644 --- a/src/bin/options.c +++ b/src/bin/options.c @@ -3,6 +3,7 @@ #include #include "options.h" #include "options_font.h" +#include "options_helpers.h" #include "options_behavior.h" #include "options_video.h" #include "options_theme.h" @@ -55,6 +56,13 @@ _cb_op_behavior(void *data, Evas_Object *obj __UNUSED__, void *event __UNUSED__) options_behavior(op_opbox, data); } +static void +_cb_op_helpers(void *data, Evas_Object *obj __UNUSED__, void *event __UNUSED__) +{ + elm_box_clear(op_opbox); + options_helpers(op_opbox, data); +} + static void _cb_op_tmp_chg(void *data, Evas_Object *obj __UNUSED__, void *event __UNUSED__) { @@ -136,6 +144,8 @@ options_toggle(Evas_Object *win, Evas_Object *bg, Evas_Object *term) "Video", _cb_op_video, term); elm_toolbar_item_append(o, "system-run", "Behavior", _cb_op_behavior, term); + elm_toolbar_item_append(o, "document-open", + "Helpers", _cb_op_helpers, term); elm_box_pack_end(op_tbox, o); evas_object_show(o); diff --git a/src/bin/options_helpers.c b/src/bin/options_helpers.c new file mode 100644 index 00000000..7f300f5a --- /dev/null +++ b/src/bin/options_helpers.c @@ -0,0 +1,373 @@ +#include "private.h" + +#include +#include "config.h" +#include "termio.h" +#include "options.h" +#include "options_helpers.h" +#include "main.h" + +static void +_cb_op_helper_inline_chg(void *data, Evas_Object *obj, void *event __UNUSED__) +{ + Evas_Object *term = data; + Config *config = termio_config_get(term); + config->helper.inline_please = elm_check_state_get(obj); + config_save(config, NULL); +} + +static void +_cb_op_helper_email_chg(void *data, Evas_Object *obj, void *event __UNUSED__) +{ + Evas_Object *term = data; + Config *config = termio_config_get(term); + char *txt; + + if (config->helper.email) + { + eina_stringshare_del(config->helper.email); + config->helper.email = NULL; + } + txt = elm_entry_markup_to_utf8(elm_object_text_get(obj)); + if (txt) + { + config->helper.email = eina_stringshare_add(txt); + free(txt); + } + config_save(config, NULL); +} + +static void +_cb_op_helper_url_image_chg(void *data, Evas_Object *obj, void *event __UNUSED__) +{ + Evas_Object *term = data; + Config *config = termio_config_get(term); + char *txt; + + if (config->helper.url.image) + { + eina_stringshare_del(config->helper.url.image); + config->helper.email = NULL; + } + txt = elm_entry_markup_to_utf8(elm_object_text_get(obj)); + if (txt) + { + config->helper.url.image = eina_stringshare_add(txt); + free(txt); + } + config_save(config, NULL); +} + +static void +_cb_op_helper_url_video_chg(void *data, Evas_Object *obj, void *event __UNUSED__) +{ + Evas_Object *term = data; + Config *config = termio_config_get(term); + char *txt; + + if (config->helper.url.video) + { + eina_stringshare_del(config->helper.url.video); + config->helper.email = NULL; + } + txt = elm_entry_markup_to_utf8(elm_object_text_get(obj)); + if (txt) + { + config->helper.url.video = eina_stringshare_add(txt); + free(txt); + } + config_save(config, NULL); +} + +static void +_cb_op_helper_url_general_chg(void *data, Evas_Object *obj, void *event __UNUSED__) +{ + Evas_Object *term = data; + Config *config = termio_config_get(term); + char *txt; + + if (config->helper.url.general) + { + eina_stringshare_del(config->helper.url.general); + config->helper.email = NULL; + } + txt = elm_entry_markup_to_utf8(elm_object_text_get(obj)); + if (txt) + { + config->helper.url.general = eina_stringshare_add(txt); + free(txt); + } + config_save(config, NULL); +} + +static void +_cb_op_helper_local_image_chg(void *data, Evas_Object *obj, void *event __UNUSED__) +{ + Evas_Object *term = data; + Config *config = termio_config_get(term); + char *txt; + + if (config->helper.local.image) + { + eina_stringshare_del(config->helper.local.image); + config->helper.email = NULL; + } + txt = elm_entry_markup_to_utf8(elm_object_text_get(obj)); + if (txt) + { + config->helper.local.image = eina_stringshare_add(txt); + free(txt); + } + config_save(config, NULL); +} + +static void +_cb_op_helper_local_video_chg(void *data, Evas_Object *obj, void *event __UNUSED__) +{ + Evas_Object *term = data; + Config *config = termio_config_get(term); + char *txt; + + if (config->helper.local.video) + { + eina_stringshare_del(config->helper.local.video); + config->helper.email = NULL; + } + txt = elm_entry_markup_to_utf8(elm_object_text_get(obj)); + if (txt) + { + config->helper.local.video = eina_stringshare_add(txt); + free(txt); + } + config_save(config, NULL); +} + +static void +_cb_op_helper_local_general_chg(void *data, Evas_Object *obj, void *event __UNUSED__) +{ + Evas_Object *term = data; + Config *config = termio_config_get(term); + char *txt; + + if (config->helper.local.general) + { + eina_stringshare_del(config->helper.local.general); + config->helper.email = NULL; + } + txt = elm_entry_markup_to_utf8(elm_object_text_get(obj)); + if (txt) + { + config->helper.local.general = eina_stringshare_add(txt); + free(txt); + } + config_save(config, NULL); +} + +void +options_helpers(Evas_Object *opbox, Evas_Object *term) +{ + Config *config = termio_config_get(term); + Evas_Object *o, *bx, *sc; + char *txt; + + o = elm_check_add(opbox); + evas_object_size_hint_weight_set(o, EVAS_HINT_EXPAND, 0.0); + evas_object_size_hint_align_set(o, EVAS_HINT_FILL, 0.5); + elm_object_text_set(o, "Inline if possible"); + elm_check_state_set(o, config->helper.inline_please); + elm_box_pack_end(opbox, o); + evas_object_show(o); + evas_object_smart_callback_add(o, "changed", + _cb_op_helper_inline_chg, term); + + o = elm_separator_add(opbox); + evas_object_size_hint_weight_set(o, EVAS_HINT_EXPAND, 0.0); + evas_object_size_hint_align_set(o, EVAS_HINT_FILL, 0.5); + elm_separator_horizontal_set(o, EINA_TRUE); + elm_box_pack_end(opbox, o); + evas_object_show(o); + + sc = o = elm_scroller_add(opbox); + evas_object_size_hint_weight_set(o, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + evas_object_size_hint_align_set(o, EVAS_HINT_FILL, EVAS_HINT_FILL); + elm_box_pack_end(opbox, o); + evas_object_show(o); + + bx = o = elm_box_add(opbox); + evas_object_size_hint_weight_set(o, EVAS_HINT_EXPAND, 0.0); + evas_object_size_hint_align_set(o, EVAS_HINT_FILL, 0.0); + elm_object_content_set(sc, o); + evas_object_show(o); + + o = elm_label_add(bx); + evas_object_size_hint_weight_set(o, 0.0, 0.0); + evas_object_size_hint_align_set(o, 0.0, 0.5); + elm_object_text_set(o, "E-mail:"); + elm_box_pack_end(bx, o); + evas_object_show(o); + + o = elm_entry_add(bx); + evas_object_size_hint_weight_set(o, EVAS_HINT_EXPAND, 0.0); + evas_object_size_hint_align_set(o, EVAS_HINT_FILL, 0.5); + elm_entry_single_line_set(o, EINA_TRUE); + elm_entry_scrollable_set(o, EINA_TRUE); + elm_entry_scrollbar_policy_set(o, ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_OFF); + txt = elm_entry_utf8_to_markup(config->helper.email); + if (txt) + { + elm_object_text_set(o, txt); + free(txt); + } + elm_box_pack_end(bx, o); + evas_object_show(o); + evas_object_smart_callback_add(o, "changed", + _cb_op_helper_email_chg, term); + + o = elm_label_add(bx); + evas_object_size_hint_weight_set(o, 0.0, 0.0); + evas_object_size_hint_align_set(o, 0.0, 0.5); + elm_object_text_set(o, "URL (Images):"); + elm_box_pack_end(bx, o); + evas_object_show(o); + + o = elm_entry_add(bx); + evas_object_size_hint_weight_set(o, EVAS_HINT_EXPAND, 0.0); + evas_object_size_hint_align_set(o, EVAS_HINT_FILL, 0.5); + elm_entry_single_line_set(o, EINA_TRUE); + elm_entry_scrollable_set(o, EINA_TRUE); + elm_entry_scrollbar_policy_set(o, ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_OFF); + txt = elm_entry_utf8_to_markup(config->helper.url.image); + if (txt) + { + elm_object_text_set(o, txt); + free(txt); + } + elm_box_pack_end(bx, o); + evas_object_show(o); + evas_object_smart_callback_add(o, "changed", + _cb_op_helper_url_image_chg, term); + + o = elm_label_add(bx); + evas_object_size_hint_weight_set(o, 0.0, 0.0); + evas_object_size_hint_align_set(o, 0.0, 0.5); + elm_object_text_set(o, "URL (Video):"); + elm_box_pack_end(bx, o); + evas_object_show(o); + + o = elm_entry_add(bx); + evas_object_size_hint_weight_set(o, EVAS_HINT_EXPAND, 0.0); + evas_object_size_hint_align_set(o, EVAS_HINT_FILL, 0.5); + elm_entry_single_line_set(o, EINA_TRUE); + elm_entry_scrollable_set(o, EINA_TRUE); + elm_entry_scrollbar_policy_set(o, ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_OFF); + txt = elm_entry_utf8_to_markup(config->helper.url.video); + if (txt) + { + elm_object_text_set(o, txt); + free(txt); + } + elm_box_pack_end(bx, o); + evas_object_show(o); + evas_object_smart_callback_add(o, "changed", + _cb_op_helper_url_video_chg, term); + + o = elm_label_add(bx); + evas_object_size_hint_weight_set(o, 0.0, 0.0); + evas_object_size_hint_align_set(o, 0.0, 0.5); + elm_object_text_set(o, "URL (All):"); + elm_box_pack_end(bx, o); + evas_object_show(o); + + o = elm_entry_add(bx); + evas_object_size_hint_weight_set(o, EVAS_HINT_EXPAND, 0.0); + evas_object_size_hint_align_set(o, EVAS_HINT_FILL, 0.5); + elm_entry_single_line_set(o, EINA_TRUE); + elm_entry_scrollable_set(o, EINA_TRUE); + elm_entry_scrollbar_policy_set(o, ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_OFF); + txt = elm_entry_utf8_to_markup(config->helper.url.general); + if (txt) + { + elm_object_text_set(o, txt); + free(txt); + } + elm_box_pack_end(bx, o); + evas_object_show(o); + evas_object_smart_callback_add(o, "changed", + _cb_op_helper_url_general_chg, term); + + o = elm_label_add(bx); + evas_object_size_hint_weight_set(o, 0.0, 0.0); + evas_object_size_hint_align_set(o, 0.0, 0.5); + elm_object_text_set(o, "Local (Images):"); + elm_box_pack_end(bx, o); + evas_object_show(o); + + o = elm_entry_add(bx); + evas_object_size_hint_weight_set(o, EVAS_HINT_EXPAND, 0.0); + evas_object_size_hint_align_set(o, EVAS_HINT_FILL, 0.5); + elm_entry_single_line_set(o, EINA_TRUE); + elm_entry_scrollable_set(o, EINA_TRUE); + elm_entry_scrollbar_policy_set(o, ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_OFF); + txt = elm_entry_utf8_to_markup(config->helper.local.image); + if (txt) + { + elm_object_text_set(o, txt); + free(txt); + } + elm_box_pack_end(bx, o); + evas_object_show(o); + evas_object_smart_callback_add(o, "changed", + _cb_op_helper_local_image_chg, term); + + o = elm_label_add(bx); + evas_object_size_hint_weight_set(o, 0.0, 0.0); + evas_object_size_hint_align_set(o, 0.0, 0.5); + elm_object_text_set(o, "Local (Video):"); + elm_box_pack_end(bx, o); + evas_object_show(o); + + o = elm_entry_add(bx); + evas_object_size_hint_weight_set(o, EVAS_HINT_EXPAND, 0.0); + evas_object_size_hint_align_set(o, EVAS_HINT_FILL, 0.5); + elm_entry_single_line_set(o, EINA_TRUE); + elm_entry_scrollable_set(o, EINA_TRUE); + elm_entry_scrollbar_policy_set(o, ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_OFF); + txt = elm_entry_utf8_to_markup(config->helper.local.video); + if (txt) + { + elm_object_text_set(o, txt); + free(txt); + } + elm_box_pack_end(bx, o); + evas_object_show(o); + evas_object_smart_callback_add(o, "changed", + _cb_op_helper_local_video_chg, term); + + o = elm_label_add(bx); + evas_object_size_hint_weight_set(o, 0.0, 0.0); + evas_object_size_hint_align_set(o, 0.0, 0.5); + elm_object_text_set(o, "Local (All):"); + elm_box_pack_end(bx, o); + evas_object_show(o); + + o = elm_entry_add(bx); + evas_object_size_hint_weight_set(o, EVAS_HINT_EXPAND, 0.0); + evas_object_size_hint_align_set(o, EVAS_HINT_FILL, 0.5); + elm_entry_single_line_set(o, EINA_TRUE); + elm_entry_scrollable_set(o, EINA_TRUE); + elm_entry_scrollbar_policy_set(o, ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_OFF); + txt = elm_entry_utf8_to_markup(config->helper.local.general); + if (txt) + { + elm_object_text_set(o, txt); + free(txt); + } + elm_box_pack_end(bx, o); + evas_object_show(o); + evas_object_smart_callback_add(o, "changed", + _cb_op_helper_local_general_chg, term); + + evas_object_size_hint_weight_set(opbox, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + evas_object_size_hint_align_set(opbox, EVAS_HINT_FILL, EVAS_HINT_FILL); + evas_object_show(o); +} diff --git a/src/bin/options_helpers.h b/src/bin/options_helpers.h new file mode 100644 index 00000000..da422e47 --- /dev/null +++ b/src/bin/options_helpers.h @@ -0,0 +1 @@ +void options_helpers(Evas_Object *opbox, Evas_Object *term); diff --git a/src/bin/termio.c b/src/bin/termio.c index 3813b696..9bf7437c 100644 --- a/src/bin/termio.c +++ b/src/bin/termio.c @@ -10,6 +10,7 @@ #include "keyin.h" #include "config.h" #include "utils.h" +#include "media.h" typedef struct _Termio Termio; @@ -43,6 +44,12 @@ struct _Termio } sel1, sel2; Eina_Bool sel : 1; } backup; + struct { + char *string; + int x1, y1, x2, y2; + int suspend; + Eina_List *objs; + } link; int zoom_fontsize_start; int scroll; unsigned int last_keyup; @@ -51,6 +58,7 @@ struct _Termio Termpty *pty; Ecore_Animator *anim; Ecore_Timer *delayed_size_timer; + Ecore_Timer *link_do_timer; Ecore_Job *mouse_move_job; Evas_Object *win; Config *config; @@ -59,6 +67,7 @@ struct _Termio Eina_Bool have_sel : 1; Eina_Bool noreqsize : 1; Eina_Bool composing : 1; + Eina_Bool didclick : 1; }; static Evas_Smart *_smart = NULL; @@ -100,8 +109,8 @@ coord_forward(Termio *sd, int *x, int *y) return EINA_TRUE; } -static void -_smart_mouseover_apply(Evas_Object *obj) +static char * +_magic_string_find(Evas_Object *obj, int cx, int cy, int *x1r, int *y1r, int *x2r, int *y2r) { Termio *sd = evas_object_smart_data_get(obj); char *s; @@ -109,11 +118,11 @@ _smart_mouseover_apply(Evas_Object *obj) int x1, x2, y1, y2, len; Eina_Bool goback = EINA_TRUE, goforward = EINA_FALSE, extend = EINA_FALSE; - if (!sd) return; - x1 = sd->mouse.cx; - y1 = sd->mouse.cy; - x2 = sd->mouse.cx; - y2 = sd->mouse.cy; + if (!sd) return NULL; + x1 = cx; + y1 = cy; + x2 = cx; + y2 = cy; if (!coord_back(sd, &x1, &y1)) goback = EINA_FALSE; for (;;) { @@ -125,6 +134,7 @@ _smart_mouseover_apply(Evas_Object *obj) { if ((!strncasecmp(s, "http://", 7))|| (!strncasecmp(s, "https://", 8)) || + (!strncasecmp(s, "file://", 7)) || (!strncasecmp(s, "ftp://", 6))) { goback = EINA_FALSE; @@ -154,7 +164,8 @@ _smart_mouseover_apply(Evas_Object *obj) else if (s[0] == '\'') endmatch = '\''; else if (s[0] == '<') endmatch = '>'; if ((!strncasecmp((s + 1), "www.", 4)) || - (!strncasecmp((s + 1), "ftp.", 4))) + (!strncasecmp((s + 1), "ftp.", 4)) || + (!strncasecmp((s + 1), "/", 1))) { goback = EINA_FALSE; coord_forward(sd, &x1, &y1); @@ -164,6 +175,9 @@ _smart_mouseover_apply(Evas_Object *obj) goback = EINA_FALSE; coord_forward(sd, &x1, &y1); } + else if (s[0] == '=') + { + } else { free(s); @@ -178,7 +192,9 @@ _smart_mouseover_apply(Evas_Object *obj) if (len > 1) { if (((endmatch) && (s[len - 1] == endmatch)) || - ((!endmatch) && (isspace(s[len - 1])))) + ((!endmatch) && + ((isspace(s[len - 1])) || (s[len - 1] == '>')) + )) { goforward = EINA_FALSE; coord_back(sd, &x2, &y2); @@ -194,7 +210,7 @@ _smart_mouseover_apply(Evas_Object *obj) { if (!coord_back(sd, &x1, &y1)) goback = EINA_FALSE; } - else if (!extend) + if ((!extend) && (!goback)) { goforward = EINA_TRUE; extend = EINA_TRUE; @@ -222,21 +238,307 @@ _smart_mouseover_apply(Evas_Object *obj) } else break; } - if (!isspace(s[0])) + if ((!isspace(s[0])) && (len > 1)) { if ((strchr(s, '@')) || (!strncasecmp(s, "http://", 7))|| (!strncasecmp(s, "https://", 8)) || (!strncasecmp(s, "ftp://", 6)) || + (!strncasecmp(s, "file://", 7)) || (!strncasecmp(s, "www.", 4)) || - (!strncasecmp(s, "ftp.", 4))) + (!strncasecmp(s, "ftp.", 4)) || + (!strncasecmp(s, "/", 1)) + ) { - printf("FOUND: '%s' @ %i,%i -> %i,%i\n", s, x1, y1, x2, y2); - // XXX: record coords and url string + if (x1r) *x1r = x1; + if (y1r) *y1r = y1; + if (x2r) *x2r = x2; + if (y2r) *y2r = y2; + return s; } } free(s); } + return NULL; +} + +static void +_activate_link(Evas_Object *obj) +{ + Termio *sd = evas_object_smart_data_get(obj); + Config *config = termio_config_get(obj); + char buf[PATH_MAX], *s; + const char *path = NULL, *cmd = NULL; + Eina_Bool url = EINA_FALSE, email = EINA_FALSE, handled = EINA_FALSE; + int type; + + if (!sd) return; + if (!config) return; + if (!sd->link.string) return; + if ((!strncasecmp(sd->link.string, "http://", 7))|| + (!strncasecmp(sd->link.string, "https://", 8)) || + (!strncasecmp(sd->link.string, "ftp://", 6)) || + (!strncasecmp(sd->link.string, "www.", 4)) || + (!strncasecmp(sd->link.string, "ftp.", 4))) + { + url = EINA_TRUE; + } + else if ((!strncasecmp(sd->link.string, "file://", 7)) || + (!strncasecmp(sd->link.string, "/", 1))) + { + path = sd->link.string; + if (!strncasecmp(sd->link.string, "file://", 7)) path = path + 7; + } + else if (strchr(sd->link.string, '@')) + { + email = EINA_TRUE; + } + + s = eina_str_escape(sd->link.string); + if (!s) return; + if (email) + { + // run mail client + cmd = "xdg-email"; + + if ((config->helper.email) && + (config->helper.email[0])) + cmd = config->helper.email; + snprintf(buf, sizeof(buf), "%s %s", cmd, s); + } + else if (path) + { + // locally accessible file + cmd = "xdg-open"; + + type = media_src_type_get(sd->link.string); + if (config->helper.inline_please) + { + if ((type == TYPE_IMG) || + (type == TYPE_SCALE) || + (type == TYPE_EDJE)) + { + evas_object_smart_callback_call(obj, "popup", NULL); + handled = EINA_TRUE; + } + else if (type == TYPE_MOV) + { + evas_object_smart_callback_call(obj, "popup", NULL); + handled = EINA_TRUE; + } + } + if (!handled) + { + if ((type == TYPE_IMG) || + (type == TYPE_SCALE) || + (type == TYPE_EDJE)) + { + if ((config->helper.local.image) && + (config->helper.local.image[0])) + cmd = config->helper.local.image; + } + else if (type == TYPE_MOV) + { + if ((config->helper.local.video) && + (config->helper.local.video[0])) + cmd = config->helper.local.video; + } + else + { + if ((config->helper.local.general) && + (config->helper.local.general[0])) + cmd = config->helper.local.general; + } + snprintf(buf, sizeof(buf), "%s %s", cmd, s); + } + } + else if (url) + { + // remote file needs ecore-con-url + cmd = "xdg-open"; + + type = media_src_type_get(sd->link.string); + if (config->helper.inline_please) + { + if ((type == TYPE_IMG) || + (type == TYPE_SCALE) || + (type == TYPE_EDJE)) + { + // XXX: begin fetch of url, once done, show + evas_object_smart_callback_call(obj, "popup", NULL); + handled = EINA_TRUE; + } + else if (type == TYPE_MOV) + { + // XXX: if no http:// add + evas_object_smart_callback_call(obj, "popup", NULL); + handled = EINA_TRUE; + } + } + if (!handled) + { + if ((type == TYPE_IMG) || + (type == TYPE_SCALE) || + (type == TYPE_EDJE)) + { + if ((config->helper.url.image) && + (config->helper.url.image[0])) + cmd = config->helper.url.image; + } + else if (type == TYPE_MOV) + { + if ((config->helper.url.video) && + (config->helper.url.video[0])) + cmd = config->helper.url.video; + } + else + { + if ((config->helper.url.general) && + (config->helper.url.general[0])) + cmd = config->helper.url.general; + } + snprintf(buf, sizeof(buf), "%s %s", cmd, s); + } + } + else + { + free(s); + return; + } + free(s); + if (!handled) ecore_exe_run(buf, NULL); +} + +static Eina_Bool +_cb_link_up_delay(void *data) +{ + Termio *sd = evas_object_smart_data_get(data); + + if (!sd) return EINA_FALSE; + sd->link_do_timer = NULL; + if (!sd->didclick) _activate_link(data); + sd->didclick = EINA_FALSE; + return EINA_FALSE; +} + +static void +_cb_link_up(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event) +{ + Evas_Event_Mouse_Up *ev = event; + Termio *sd = evas_object_smart_data_get(data); + + if (!sd) return; + if (ev->button == 1) + { + if (sd->link_do_timer) ecore_timer_del(sd->link_do_timer); + sd->link_do_timer = ecore_timer_add(0.2, _cb_link_up_delay, data); + } +} + +static void +_update_link(Evas_Object *obj, Eina_Bool same_link, Eina_Bool same_geom) +{ + Termio *sd = evas_object_smart_data_get(obj); + + if (!sd) return; + + if (!same_link) + { + // check link and re-probe/fetch create popup preview + } + + if (!same_geom) + { + Evas_Coord ox, oy, ow, oh; + Evas_Object *o; + // fix up edje objects "underlining" the link + int y; + + evas_object_geometry_get(obj, &ox, &oy, &ow, &oh); + EINA_LIST_FREE(sd->link.objs, o) evas_object_del(o); + if ((sd->link.string) && (sd->link.suspend == 0)) + { + for (y = sd->link.y1; y <= sd->link.y2; y++) + { + o = edje_object_add(evas_object_evas_get(obj)); + evas_object_smart_member_add(o, obj); + theme_apply(o, sd->config, "terminology/link"); + + if (y == sd->link.y1) + { + evas_object_move(o, ox + (sd->link.x1 * sd->font.chw), + oy + (y * sd->font.chh)); + if (sd->link.y1 == sd->link.y2) + evas_object_resize(o, + ((sd->link.x2 - sd->link.x1 + 1) * sd->font.chw), + sd->font.chh); + else + evas_object_resize(o, + ((sd->grid.w - sd->link.x1) * sd->font.chw), + sd->font.chh); + } + else if (y == sd->link.y2) + { + evas_object_move(o, ox, oy + (y * sd->font.chh)); + evas_object_resize(o, + ((sd->link.x2 + 1) * sd->font.chw), + sd->font.chh); + } + else + { + evas_object_move(o, ox, oy + (y * sd->font.chh)); + evas_object_resize(o, (sd->grid.w * sd->font.chw), + sd->font.chh); + } + + sd->link.objs = eina_list_append(sd->link.objs, o); + evas_object_show(o); + evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_UP, + _cb_link_up, obj); + } + } + } +} + +static void +_smart_mouseover_apply(Evas_Object *obj) +{ + char *s; + int x1 = 0, y1 = 0, x2 = 0, y2 = 0; + Eina_Bool same_link = EINA_FALSE, same_geom = EINA_FALSE; + Termio *sd = evas_object_smart_data_get(obj); + + if (!sd) return; + + s = _magic_string_find(obj, sd->mouse.cx, sd->mouse.cy, + &x1, &y1, &x2, &y2); + if (!s) + { + if (sd->link.string) free(sd->link.string); + sd->link.string = NULL; + sd->link.x1 = -1; + sd->link.y1 = -1; + sd->link.x2 = -1; + sd->link.y2 = -1; + _update_link(obj, same_link, same_geom); + return; + } + + if ((sd->link.string) && (!strcmp(sd->link.string, s))) + same_link = EINA_TRUE; + if (sd->link.string) free(sd->link.string); + sd->link.string = s; + if ((x1 == sd->link.x1) && (y1 == sd->link.y1) && + (x2 == sd->link.x2) && (y2 == sd->link.y2)) + same_geom = EINA_TRUE; + if (((sd->link.suspend != 0) && (sd->link.objs)) || + ((sd->link.suspend == 0) && (!sd->link.objs))) + same_geom = EINA_FALSE; + sd->link.x1 = x1; + sd->link.y1 = y1; + sd->link.x2 = x2; + sd->link.y2 = y2; + _update_link(obj, same_link, same_geom); } static void @@ -1272,12 +1574,14 @@ _smart_cb_mouse_down(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__ if (!sd) return; _smart_xy_to_cursor(data, ev->canvas.x, ev->canvas.y, &cx, &cy); _rep_mouse_down(data, ev, cx, cy); + sd->didclick = EINA_FALSE; if (ev->button == 1) { if (ev->flags & EVAS_BUTTON_TRIPLE_CLICK) { _sel_line(data, cx, cy - sd->scroll); if (sd->cur.sel) _take_selection(data, ELM_SEL_TYPE_PRIMARY); + sd->didclick = EINA_TRUE; } else if (ev->flags & EVAS_BUTTON_DOUBLE_CLICK) { @@ -1296,6 +1600,7 @@ _smart_cb_mouse_down(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__ _sel_word(data, cx, cy - sd->scroll); } if (sd->cur.sel) _take_selection(data, ELM_SEL_TYPE_PRIMARY); + sd->didclick = EINA_TRUE; } else { @@ -1304,7 +1609,11 @@ _smart_cb_mouse_down(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__ sd->backup.sel1.y = sd->cur.sel1.y; sd->backup.sel2.x = sd->cur.sel2.x; sd->backup.sel2.y = sd->cur.sel2.y; - if (sd->cur.sel) sd->cur.sel = 0; + if (sd->cur.sel) + { + sd->cur.sel = 0; + sd->didclick = EINA_TRUE; + } sd->cur.makesel = 1; sd->cur.sel1.x = cx; sd->cur.sel1.y = cy - sd->scroll; @@ -1336,6 +1645,7 @@ _smart_cb_mouse_up(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, sd->cur.makesel = 0; if (sd->cur.sel) { + sd->didclick = EINA_TRUE; sd->cur.sel2.x = cx; sd->cur.sel2.y = cy - sd->scroll; _selection_dbl_fix(data); @@ -1380,6 +1690,18 @@ _smart_cb_mouse_move(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__ } } +static void +_smart_cb_mouse_in(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event __UNUSED__) +{ + termio_mouseover_suspend_pushpop(data, -1); +} + +static void +_smart_cb_mouse_out(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event __UNUSED__) +{ + termio_mouseover_suspend_pushpop(data, 1); +} + static void _smart_cb_mouse_wheel(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event) { @@ -1468,6 +1790,7 @@ _smart_cb_gest_long_move(void *data, void *event __UNUSED__) if (!sd) return EVAS_EVENT_FLAG_ON_HOLD; evas_object_smart_callback_call(data, "options", NULL); + sd->didclick = EINA_TRUE; return EVAS_EVENT_FLAG_ON_HOLD; } @@ -1484,6 +1807,7 @@ _smart_cb_gest_zoom_start(void *data, void *event) sd->zoom_fontsize_start = config->font.size; _font_size_set(data, (double)sd->zoom_fontsize_start * p->zoom); } + sd->didclick = EINA_TRUE; return EVAS_EVENT_FLAG_ON_HOLD; } @@ -1500,6 +1824,7 @@ _smart_cb_gest_zoom_move(void *data, void *event) sd->zoom_fontsize_start = config->font.size; _font_size_set(data, (double)sd->zoom_fontsize_start * p->zoom); } + sd->didclick = EINA_TRUE; return EVAS_EVENT_FLAG_ON_HOLD; } @@ -1516,6 +1841,7 @@ _smart_cb_gest_zoom_end(void *data, void *event) sd->zoom_fontsize_start = config->font.size; _font_size_set(data, (double)sd->zoom_fontsize_start * p->zoom); } + sd->didclick = EINA_TRUE; return EVAS_EVENT_FLAG_ON_HOLD; } @@ -1532,6 +1858,7 @@ _smart_cb_gest_zoom_abort(void *data, void *event __UNUSED__) sd->zoom_fontsize_start = config->font.size; _font_size_set(data, sd->zoom_fontsize_start); } + sd->didclick = EINA_TRUE; return EVAS_EVENT_FLAG_ON_HOLD; } @@ -1631,6 +1958,10 @@ _smart_add(Evas_Object *obj) _smart_cb_mouse_up, obj); evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_MOVE, _smart_cb_mouse_move, obj); + evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_IN, + _smart_cb_mouse_in, obj); + evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_OUT, + _smart_cb_mouse_out, obj); evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_WHEEL, _smart_cb_mouse_wheel, obj); @@ -1643,6 +1974,8 @@ _smart_add(Evas_Object *obj) evas_object_event_callback_add(obj, EVAS_CALLBACK_FOCUS_OUT, _smart_cb_focus_out, obj); + sd->link.suspend = 1; + if (ecore_imf_init()) { const char *imf_id = ecore_imf_context_default_id_get(); @@ -1699,7 +2032,9 @@ static void _smart_del(Evas_Object *obj) { char *str; + Evas_Object *o; Termio *sd = evas_object_smart_data_get(obj); + if (!sd) return; if (sd->imf) { @@ -1714,9 +2049,12 @@ _smart_del(Evas_Object *obj) if (sd->cur.selo3) evas_object_del(sd->cur.selo3); if (sd->anim) ecore_animator_del(sd->anim); if (sd->delayed_size_timer) ecore_timer_del(sd->delayed_size_timer); + if (sd->link_do_timer) ecore_timer_del(sd->link_do_timer); if (sd->mouse_move_job) ecore_job_del(sd->mouse_move_job); if (sd->font.name) eina_stringshare_del(sd->font.name); if (sd->pty) termpty_free(sd->pty); + if (sd->link.string) free(sd->link.string); + EINA_LIST_FREE(sd->link.objs, o) evas_object_del(o); EINA_LIST_FREE(sd->seq, str) eina_stringshare_del(str); sd->cur.obj = NULL; sd->event = NULL; @@ -1993,6 +2331,7 @@ termio_selection_get(Evas_Object *obj, int c1x, int c1y, int c2x, int c2y) w = 0; last0 = -1; cells = termpty_cellrow_get(sd->pty, y, &w); + if (!cells) continue; if (w > sd->grid.w) w = sd->grid.w; start_x = c1x; end_x = c2x; @@ -2165,3 +2504,21 @@ termio_paste_clipboard(Evas_Object *obj) { _paste_selection(obj, ELM_SEL_TYPE_CLIPBOARD); } + +const char * +termio_link_get(const Evas_Object *obj) +{ + Termio *sd = evas_object_smart_data_get(obj); + EINA_SAFETY_ON_NULL_RETURN_VAL(sd, NULL); + return sd->link.string; +} + +void +termio_mouseover_suspend_pushpop(Evas_Object *obj, int dir) +{ + Termio *sd = evas_object_smart_data_get(obj); + if (!sd) return; + sd->link.suspend += dir; + if (sd->link.suspend < 0) sd->link.suspend = 0; + _smart_update_queue(obj, sd); +} diff --git a/src/bin/termio.h b/src/bin/termio.h index d7274681..108d5359 100644 --- a/src/bin/termio.h +++ b/src/bin/termio.h @@ -10,5 +10,6 @@ void termio_config_update(Evas_Object *obj); Config *termio_config_get(const Evas_Object *obj); void termio_copy_clipboard(Evas_Object *obj); void termio_paste_clipboard(Evas_Object *obj); - +const char *termio_link_get(const Evas_Object *obj); +void termio_mouseover_suspend_pushpop(Evas_Object *obj, int dir); #endif