summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBoris Faure <billiob@gmail.com>2015-04-05 12:13:04 +0200
committerBoris Faure <billiob@gmail.com>2015-04-05 12:14:46 +0200
commit7e4276c0333c7bad262c6eef5fb60e265684cf9b (patch)
tree0ae66bd45180dda8bcc984b98344fde357830daa /src
parent563517fbc906cde3e13040612fe99811bffbde32 (diff)
right click on a selection shows popup to copy it
Closes T2246
Diffstat (limited to 'src')
-rw-r--r--src/bin/termio.c133
1 files changed, 105 insertions, 28 deletions
diff --git a/src/bin/termio.c b/src/bin/termio.c
index 527def6..4f03072 100644
--- a/src/bin/termio.c
+++ b/src/bin/termio.c
@@ -53,7 +53,6 @@ struct _Termio
53 int x1, y1, x2, y2; 53 int x1, y1, x2, y2;
54 int suspend; 54 int suspend;
55 Eina_List *objs; 55 Eina_List *objs;
56 Evas_Object *ctxpopup;
57 struct { 56 struct {
58 Evas_Object *dndobj; 57 Evas_Object *dndobj;
59 Evas_Coord x, y; 58 Evas_Coord x, y;
@@ -62,6 +61,7 @@ struct _Termio
62 unsigned char dndobjdel : 1; 61 unsigned char dndobjdel : 1;
63 } down; 62 } down;
64 } link; 63 } link;
64 Evas_Object *ctxpopup;
65 int zoom_fontsize_start; 65 int zoom_fontsize_start;
66 int scroll; 66 int scroll;
67 Evas_Object *self; 67 Evas_Object *self;
@@ -111,7 +111,9 @@ static void _smart_update_queue(Evas_Object *obj, Termio *sd);
111static void _smart_apply(Evas_Object *obj); 111static void _smart_apply(Evas_Object *obj);
112static void _smart_size(Evas_Object *obj, int w, int h, Eina_Bool force); 112static void _smart_size(Evas_Object *obj, int w, int h, Eina_Bool force);
113static void _smart_calculate(Evas_Object *obj); 113static void _smart_calculate(Evas_Object *obj);
114static void _take_selection_text(Evas_Object *obj, Elm_Sel_Type type, const char *text); 114static void _take_selection_text(Termio *sd, Elm_Sel_Type type, const char *text);
115static void _smart_xy_to_cursor(Termio *sd, Evas_Coord x, Evas_Coord y, int *cx, int *cy);
116static Eina_Bool _mouse_in_selection(Termio *sd, int cx, int cy);
115 117
116 118
117/* {{{ Helpers */ 119/* {{{ Helpers */
@@ -689,7 +691,7 @@ termio_config_set(Evas_Object *obj, Config *config)
689/* }}} */ 691/* }}} */
690/* {{{ Links */ 692/* {{{ Links */
691 693
692static inline Eina_Bool 694static Eina_Bool
693_should_inline(const Evas_Object *obj) 695_should_inline(const Evas_Object *obj)
694{ 696{
695 const Config *config = termio_config_get(obj); 697 const Config *config = termio_config_get(obj);
@@ -878,7 +880,7 @@ _cb_ctxp_del(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED,
878{ 880{
879 Termio *sd = data; 881 Termio *sd = data;
880 EINA_SAFETY_ON_NULL_RETURN(sd); 882 EINA_SAFETY_ON_NULL_RETURN(sd);
881 sd->link.ctxpopup = NULL; 883 sd->ctxpopup = NULL;
882 elm_object_focus_set(sd->self, EINA_TRUE); 884 elm_object_focus_set(sd->self, EINA_TRUE);
883} 885}
884 886
@@ -912,7 +914,7 @@ _cb_ctxp_link_copy(void *data, Evas_Object *obj, void *event EINA_UNUSED)
912 Termio *sd = evas_object_smart_data_get(term); 914 Termio *sd = evas_object_smart_data_get(term);
913 EINA_SAFETY_ON_NULL_RETURN(sd); 915 EINA_SAFETY_ON_NULL_RETURN(sd);
914 EINA_SAFETY_ON_NULL_RETURN(sd->link.string); 916 EINA_SAFETY_ON_NULL_RETURN(sd->link.string);
915 _take_selection_text(term, ELM_SEL_TYPE_CLIPBOARD, sd->link.string); 917 _take_selection_text(sd, ELM_SEL_TYPE_CLIPBOARD, sd->link.string);
916 evas_object_del(obj); 918 evas_object_del(obj);
917} 919}
918 920
@@ -931,8 +933,19 @@ _cb_link_down(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, voi
931 } 933 }
932 else if (ev->button == 3) 934 else if (ev->button == 3)
933 { 935 {
934 Evas_Object *ctxp = elm_ctxpopup_add(sd->win); 936 Evas_Object *ctxp;
935 sd->link.ctxpopup = ctxp; 937
938 if (sd->pty->selection.is_active)
939 {
940 int cx = 0, cy = 0;
941
942 _smart_xy_to_cursor(sd, ev->canvas.x, ev->canvas.y, &cx, &cy);
943 if (_mouse_in_selection(sd, cx, cy))
944 return;
945 }
946
947 ctxp = elm_ctxpopup_add(sd->win);
948 sd->ctxpopup = ctxp;
936 949
937 if (sd->config->helper.inline_please) 950 if (sd->config->helper.inline_please)
938 { 951 {
@@ -1936,6 +1949,42 @@ end:
1936/* }}} */ 1949/* }}} */
1937/* {{{ Selection */ 1950/* {{{ Selection */
1938 1951
1952static Eina_Bool
1953_mouse_in_selection(Termio *sd, int cx, int cy)
1954{
1955 int start_x = 0, start_y = 0, end_x = 0, end_y = 0;
1956
1957 if (!sd->pty->selection.is_active)
1958 return EINA_FALSE;
1959
1960 start_x = sd->pty->selection.start.x;
1961 start_y = sd->pty->selection.start.y;
1962 end_x = sd->pty->selection.end.x;
1963 end_y = sd->pty->selection.end.y;
1964
1965 if (!sd->pty->selection.is_top_to_bottom)
1966 {
1967 INT_SWAP(start_y, end_y);
1968 INT_SWAP(start_x, end_x);
1969 }
1970 if (sd->pty->selection.is_box)
1971 {
1972 if ((start_y <= cy) && (cy <= end_y) &&
1973 (start_x <= cx) && (cx <= end_x) )
1974 return EINA_TRUE;
1975 }
1976 else
1977 {
1978 if ((cy < start_y) || (cy > end_y))
1979 return EINA_FALSE;
1980 if (((cy == start_y) && (cx < start_x)) ||
1981 ((cy == end_y) && (cx > end_x)))
1982 return EINA_FALSE;
1983 return EINA_TRUE;
1984 }
1985 return EINA_FALSE;
1986}
1987
1939struct termio_sb { 1988struct termio_sb {
1940 char *buf; 1989 char *buf;
1941 size_t len; 1990 size_t len;
@@ -1965,7 +2014,7 @@ _sb_add(struct termio_sb *sb, const char *s, size_t len)
1965} 2014}
1966 2015
1967/* unlike eina_strbuf_rtrim, only trims \t, \f, ' ' */ 2016/* unlike eina_strbuf_rtrim, only trims \t, \f, ' ' */
1968void 2017static void
1969_sb_spaces_rtrim(struct termio_sb *sb) 2018_sb_spaces_rtrim(struct termio_sb *sb)
1970{ 2019{
1971 if (!sb->buf) 2020 if (!sb->buf)
@@ -2222,10 +2271,8 @@ _lost_selection(void *data, Elm_Sel_Type selection)
2222} 2271}
2223 2272
2224static void 2273static void
2225_take_selection_text(Evas_Object *obj, Elm_Sel_Type type, const char *text) 2274_take_selection_text(Termio *sd, Elm_Sel_Type type, const char *text)
2226{ 2275{
2227 Termio *sd = evas_object_smart_data_get(obj);
2228
2229 EINA_SAFETY_ON_NULL_RETURN(sd); 2276 EINA_SAFETY_ON_NULL_RETURN(sd);
2230 2277
2231 text = eina_stringshare_add(text); 2278 text = eina_stringshare_add(text);
@@ -2239,7 +2286,7 @@ _take_selection_text(Evas_Object *obj, Elm_Sel_Type type, const char *text)
2239 text, 2286 text,
2240 eina_stringshare_strlen(text)); 2287 eina_stringshare_strlen(text));
2241 elm_cnp_selection_loss_callback_set(sd->win, type, 2288 elm_cnp_selection_loss_callback_set(sd->win, type,
2242 _lost_selection, obj); 2289 _lost_selection, sd->self);
2243 sd->have_sel = EINA_TRUE; 2290 sd->have_sel = EINA_TRUE;
2244 if (sd->sel_str) eina_stringshare_del(sd->sel_str); 2291 if (sd->sel_str) eina_stringshare_del(sd->sel_str);
2245 sd->sel_str = text; 2292 sd->sel_str = text;
@@ -2305,7 +2352,7 @@ termio_take_selection(Evas_Object *obj, Elm_Sel_Type type)
2305 if (s) 2352 if (s)
2306 { 2353 {
2307 if ((sd->win) && (len > 0)) 2354 if ((sd->win) && (len > 0))
2308 _take_selection_text(obj, type, s); 2355 _take_selection_text(sd, type, s);
2309 free(s); 2356 free(s);
2310 } 2357 }
2311} 2358}
@@ -3341,7 +3388,7 @@ _smart_cb_focus_out(void *data, Evas *e EINA_UNUSED, Evas_Object *obj,
3341 Termio *sd = evas_object_smart_data_get(data); 3388 Termio *sd = evas_object_smart_data_get(data);
3342 EINA_SAFETY_ON_NULL_RETURN(sd); 3389 EINA_SAFETY_ON_NULL_RETURN(sd);
3343 3390
3344 if (sd->link.ctxpopup) return; /* ctxp triggers focus out we should ignore */ 3391 if (sd->ctxpopup) return; /* ctxp triggers focus out we should ignore */
3345 3392
3346 edje_object_signal_emit(sd->cursor.obj, "focus,out", "terminology"); 3393 edje_object_signal_emit(sd->cursor.obj, "focus,out", "terminology");
3347 if (!sd->win) return; 3394 if (!sd->win) return;
@@ -3404,14 +3451,13 @@ _smart_mouseover_apply(Evas_Object *obj)
3404} 3451}
3405 3452
3406static void 3453static void
3407_smart_xy_to_cursor(Evas_Object *obj, Evas_Coord x, Evas_Coord y, 3454_smart_xy_to_cursor(Termio *sd, Evas_Coord x, Evas_Coord y,
3408 int *cx, int *cy) 3455 int *cx, int *cy)
3409{ 3456{
3410 Termio *sd = evas_object_smart_data_get(obj);
3411 EINA_SAFETY_ON_NULL_RETURN(sd);
3412 Evas_Coord ox, oy; 3457 Evas_Coord ox, oy;
3458 EINA_SAFETY_ON_NULL_RETURN(sd);
3413 3459
3414 evas_object_geometry_get(obj, &ox, &oy, NULL, NULL); 3460 evas_object_geometry_get(sd->self, &ox, &oy, NULL, NULL);
3415 *cx = (x - ox) / sd->font.chw; 3461 *cx = (x - ox) / sd->font.chw;
3416 *cy = (y - oy) / sd->font.chh; 3462 *cy = (y - oy) / sd->font.chh;
3417 if (*cx < 0) *cx = 0; 3463 if (*cx < 0) *cx = 0;
@@ -3863,6 +3909,38 @@ _handle_mouse_down_single_click(Termio *sd,
3863} 3909}
3864 3910
3865static void 3911static void
3912_cb_ctxp_sel_copy(void *data, Evas_Object *obj, void *event EINA_UNUSED)
3913{
3914 termio_take_selection(data, ELM_SEL_TYPE_CLIPBOARD);
3915 evas_object_del(obj);
3916}
3917
3918static void
3919_handle_right_click(Evas_Object *obj, Evas_Event_Mouse_Down *ev, Termio *sd,
3920 int cx, int cy)
3921{
3922 elm_object_focus_set(obj, EINA_TRUE);
3923 if (_mouse_in_selection(sd, cx, cy))
3924 {
3925 Evas_Object *ctxp;
3926 ctxp = elm_ctxpopup_add(sd->win);
3927 sd->ctxpopup = ctxp;
3928
3929 elm_ctxpopup_item_append(ctxp, _("Copy"), NULL, _cb_ctxp_sel_copy,
3930 sd->self);
3931 evas_object_move(ctxp, ev->canvas.x, ev->canvas.y);
3932 evas_object_show(ctxp);
3933 evas_object_smart_callback_add(ctxp, "dismissed",
3934 _cb_ctxp_dismissed, sd);
3935 evas_object_event_callback_add(ctxp, EVAS_CALLBACK_DEL,
3936 _cb_ctxp_del, sd);
3937 return;
3938 }
3939 if (!sd->link.string)
3940 evas_object_smart_callback_call(obj, "options", NULL);
3941}
3942
3943static void
3866_smart_cb_mouse_down(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event) 3944_smart_cb_mouse_down(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event)
3867{ 3945{
3868 Evas_Event_Mouse_Down *ev = event; 3946 Evas_Event_Mouse_Down *ev = event;
@@ -3875,10 +3953,11 @@ _smart_cb_mouse_down(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUS
3875 shift = evas_key_modifier_is_set(ev->modifiers, "Shift"); 3953 shift = evas_key_modifier_is_set(ev->modifiers, "Shift");
3876 ctrl = evas_key_modifier_is_set(ev->modifiers, "Control"); 3954 ctrl = evas_key_modifier_is_set(ev->modifiers, "Control");
3877 alt = evas_key_modifier_is_set(ev->modifiers, "Alt"); 3955 alt = evas_key_modifier_is_set(ev->modifiers, "Alt");
3878 _smart_xy_to_cursor(data, ev->canvas.x, ev->canvas.y, &cx, &cy); 3956 _smart_xy_to_cursor(sd, ev->canvas.x, ev->canvas.y, &cx, &cy);
3957
3879 if ((ev->button == 3) && ctrl) 3958 if ((ev->button == 3) && ctrl)
3880 { 3959 {
3881 evas_object_smart_callback_call(data, "options", NULL); 3960 _handle_right_click(data, ev, sd, cx, cy);
3882 return; 3961 return;
3883 } 3962 }
3884 if (!shift && !ctrl) 3963 if (!shift && !ctrl)
@@ -3928,9 +4007,7 @@ _smart_cb_mouse_down(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUS
3928 } 4007 }
3929 else if (ev->button == 3) 4008 else if (ev->button == 3)
3930 { 4009 {
3931 elm_object_focus_set(data, EINA_TRUE); 4010 _handle_right_click(data, ev, sd, cx, cy);
3932 if (!sd->link.string)
3933 evas_object_smart_callback_call(data, "options", NULL);
3934 } 4011 }
3935} 4012}
3936 4013
@@ -3947,7 +4024,7 @@ _smart_cb_mouse_up(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED
3947 shift = evas_key_modifier_is_set(ev->modifiers, "Shift"); 4024 shift = evas_key_modifier_is_set(ev->modifiers, "Shift");
3948 ctrl = evas_key_modifier_is_set(ev->modifiers, "Control"); 4025 ctrl = evas_key_modifier_is_set(ev->modifiers, "Control");
3949 4026
3950 _smart_xy_to_cursor(data, ev->canvas.x, ev->canvas.y, &cx, &cy); 4027 _smart_xy_to_cursor(sd, ev->canvas.x, ev->canvas.y, &cx, &cy);
3951 if (!shift && !ctrl && !sd->pty->selection.makesel) 4028 if (!shift && !ctrl && !sd->pty->selection.makesel)
3952 if (_rep_mouse_up(sd, ev, cx, cy)) 4029 if (_rep_mouse_up(sd, ev, cx, cy))
3953 { 4030 {
@@ -4162,7 +4239,7 @@ _smart_cb_mouse_in(void *data, Evas *e EINA_UNUSED,
4162 Termio *sd = evas_object_smart_data_get(data); 4239 Termio *sd = evas_object_smart_data_get(data);
4163 4240
4164 EINA_SAFETY_ON_NULL_RETURN(sd); 4241 EINA_SAFETY_ON_NULL_RETURN(sd);
4165 _smart_xy_to_cursor(data, ev->canvas.x, ev->canvas.y, &cx, &cy); 4242 _smart_xy_to_cursor(sd, ev->canvas.x, ev->canvas.y, &cx, &cy);
4166 sd->mouse.cx = cx; 4243 sd->mouse.cx = cx;
4167 sd->mouse.cy = cy; 4244 sd->mouse.cy = cy;
4168 termio_mouseover_suspend_pushpop(data, -1); 4245 termio_mouseover_suspend_pushpop(data, -1);
@@ -4177,7 +4254,7 @@ _smart_cb_mouse_out(void *data, Evas *e EINA_UNUSED, Evas_Object *obj,
4177 4254
4178 EINA_SAFETY_ON_NULL_RETURN(sd); 4255 EINA_SAFETY_ON_NULL_RETURN(sd);
4179 4256
4180 if (sd->link.ctxpopup) return; /* ctxp triggers mouse out we should ignore */ 4257 if (sd->ctxpopup) return; /* ctxp triggers mouse out we should ignore */
4181 4258
4182 termio_mouseover_suspend_pushpop(data, 1); 4259 termio_mouseover_suspend_pushpop(data, 1);
4183 ty_dbus_link_hide(); 4260 ty_dbus_link_hide();
@@ -4191,7 +4268,7 @@ _smart_cb_mouse_out(void *data, Evas *e EINA_UNUSED, Evas_Object *obj,
4191 { 4268 {
4192 int cx = 0, cy = 0; 4269 int cx = 0, cy = 0;
4193 4270
4194 _smart_xy_to_cursor(data, ev->canvas.x, ev->canvas.y, &cx, &cy); 4271 _smart_xy_to_cursor(sd, ev->canvas.x, ev->canvas.y, &cx, &cy);
4195 sd->mouse.cx = cx; 4272 sd->mouse.cx = cx;
4196 sd->mouse.cy = cy; 4273 sd->mouse.cy = cy;
4197 } 4274 }
@@ -4245,7 +4322,7 @@ _smart_cb_mouse_wheel(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNU
4245 { 4322 {
4246 int cx = 0, cy = 0; 4323 int cx = 0, cy = 0;
4247 4324
4248 _smart_xy_to_cursor(data, ev->canvas.x, ev->canvas.y, &cx, &cy); 4325 _smart_xy_to_cursor(sd, ev->canvas.x, ev->canvas.y, &cx, &cy);
4249 4326
4250 switch (sd->pty->mouse_ext) 4327 switch (sd->pty->mouse_ext)
4251 { 4328 {