summaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
authorChris Michael <cp.michael@samsung.com>2013-11-07 11:57:14 +0000
committerChris Michael <cp.michael@samsung.com>2013-11-07 14:31:57 +0000
commitf0eea6c266d8621b9316f8f98a468617d5d6ce5b (patch)
tree039fe795053bbd15c385246e0d852c1aef5bf991 /src/lib
parent800821735fc8b66f092964afa92a02294d8c869b (diff)
Fix elementary copy/paste for wayland. Rework copy/paste code in elm.
This is part of a larger copy/paste fix for efl/elm wayland. Previously, copy/paste would not work via keyboard shortcuts. This series of changes fixes that issue (wrt elm_entry anyway). This also adds addtional copy/paste support (wrt efl wayland), including support for various mime types (text/plain, elm-markup, and html). Signed-off-by: Chris Michael <cp.michael@samsung.com>
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/elm_cnp.c285
1 files changed, 253 insertions, 32 deletions
diff --git a/src/lib/elm_cnp.c b/src/lib/elm_cnp.c
index b321de1c8..a40f87b33 100644
--- a/src/lib/elm_cnp.c
+++ b/src/lib/elm_cnp.c
@@ -2147,11 +2147,31 @@ struct _Wl_Cnp_Selection
2147 2147
2148 Evas_Object *widget; 2148 Evas_Object *widget;
2149 Evas_Object *requestwidget; 2149 Evas_Object *requestwidget;
2150
2151 void *udata;
2152 Elm_Sel_Type seltype;
2153 Elm_Sel_Format requestformat;
2154 Elm_Drop_Cb datacb;
2155
2156 Elm_Selection_Loss_Cb loss_cb;
2157 void *loss_data;
2158
2159 Elm_Sel_Format format;
2160 Ecore_Wl_Window *win;
2161 Elm_Xdnd_Action action;
2162
2163 Eina_Bool active : 1;
2150}; 2164};
2151 2165
2152static Eina_Bool _wl_elm_cnp_init(void); 2166static Eina_Bool _wl_elm_cnp_init(void);
2153 2167
2154static Wl_Cnp_Selection wl_cnp_selection = {0, 0, NULL, NULL}; 2168static Wl_Cnp_Selection wl_cnp_selection =
2169{
2170 0, 0, NULL, NULL,
2171 NULL, 0, 0, NULL, NULL, NULL,
2172 0, NULL, 0, EINA_FALSE
2173};
2174
2155static void _wl_sel_obj_del2(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__); 2175static void _wl_sel_obj_del2(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__);
2156static Eina_Bool _wl_elm_cnp_selection_set(Evas_Object *obj __UNUSED__, Elm_Sel_Type selection, Elm_Sel_Format format __UNUSED__, const void *selbuf, size_t buflen); 2176static Eina_Bool _wl_elm_cnp_selection_set(Evas_Object *obj __UNUSED__, Elm_Sel_Type selection, Elm_Sel_Format format __UNUSED__, const void *selbuf, size_t buflen);
2157static Eina_Bool _wl_elm_cnp_selection_get(Evas_Object *obj, Elm_Sel_Type selection, Elm_Sel_Format format __UNUSED__, Elm_Drop_Cb datacb __UNUSED__, void *udata __UNUSED__); 2177static Eina_Bool _wl_elm_cnp_selection_get(Evas_Object *obj, Elm_Sel_Type selection, Elm_Sel_Format format __UNUSED__, Elm_Drop_Cb datacb __UNUSED__, void *udata __UNUSED__);
@@ -2188,6 +2208,14 @@ static Eina_Bool _wl_drops_accept(const char *type);
2188static unsigned int _wl_elm_widget_window_get(Evas_Object *obj); 2208static unsigned int _wl_elm_widget_window_get(Evas_Object *obj);
2189 2209
2190static void 2210static void
2211_wl_sel_obj_del(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
2212{
2213 Wl_Cnp_Selection *sel = data;
2214 if (sel->widget == obj) sel->widget = NULL;
2215 if (dragwidget == obj) dragwidget = NULL;
2216}
2217
2218static void
2191_wl_sel_obj_del2(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__) 2219_wl_sel_obj_del2(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
2192{ 2220{
2193 Wl_Cnp_Selection *sel = data; 2221 Wl_Cnp_Selection *sel = data;
@@ -2195,59 +2223,187 @@ _wl_sel_obj_del2(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_i
2195} 2223}
2196 2224
2197static Eina_Bool 2225static Eina_Bool
2198_wl_elm_cnp_selection_set(Evas_Object *obj __UNUSED__, Elm_Sel_Type selection, Elm_Sel_Format format __UNUSED__, const void *selbuf, size_t buflen) 2226_wl_elm_cnp_selection_set(Evas_Object *obj, Elm_Sel_Type selection, Elm_Sel_Format format, const void *selbuf, size_t buflen)
2199{ 2227{
2200 const char *types[10] = {0, }; 2228 Ecore_Wl_Window *win;
2229 Wl_Cnp_Selection *sel = &wl_cnp_selection;
2230
2231 if ((!selbuf) && (format != ELM_SEL_FORMAT_IMAGE))
2232 return elm_object_cnp_selection_clear(obj, selection);
2201 2233
2202 _wl_elm_cnp_init(); 2234 _wl_elm_cnp_init();
2203 2235
2204 /* TODO: other EML_SEL_TYPE and ELM_SEL_FORMAT */ 2236 win = elm_win_wl_window_get(obj);
2205 if (ELM_SEL_TYPE_CLIPBOARD == selection) 2237
2238 if (sel->loss_cb) sel->loss_cb(sel->loss_data, selection);
2239
2240 if (sel->widget)
2241 evas_object_event_callback_del_full(sel->widget,
2242 EVAS_CALLBACK_DEL,
2243 _wl_sel_obj_del, &wl_cnp_selection);
2244 sel->widget = NULL;
2245
2246 sel->active = EINA_TRUE;
2247 sel->seltype = selection;
2248 sel->widget = obj;
2249 sel->win = win;
2250 /* sel->set(win, &selection, sizeof(Elm_Sel_Type)); */
2251 sel->format = format;
2252 sel->loss_cb = NULL;
2253 sel->loss_data = NULL;
2254
2255 evas_object_event_callback_add
2256 (sel->widget, EVAS_CALLBACK_DEL, _wl_sel_obj_del,
2257 &wl_cnp_selection);
2258
2259 if (selbuf)
2206 { 2260 {
2207 types[0] = "text/plain;charset=utf-8"; 2261 if (format & ELM_SEL_FORMAT_IMAGE)
2208 ecore_wl_dnd_selection_set(ecore_wl_input_get(), types); 2262 {
2263 /* FIXME */
2264 // selbuf is actual image data, not text/string
2265 sel->selbuf = malloc(buflen + 1);
2266 if (!sel->selbuf)
2267 {
2268 elm_object_cnp_selection_clear(obj, selection);
2269 return EINA_FALSE;
2270 }
2271 memcpy(sel->selbuf, selbuf, buflen);
2272 sel->selbuf[buflen] = 0;
2273 }
2274 else
2275 {
2276 const char *types[10] = {0, };
2277 int i = -1;
2209 2278
2210 if (wl_cnp_selection.selbuf) free(wl_cnp_selection.selbuf); 2279 if (format & ELM_SEL_FORMAT_TEXT)
2211 wl_cnp_selection.selbuf = strdup((char*)selbuf); 2280 {
2212 wl_cnp_selection.buflen = buflen; 2281 types[++i] = "text/plain";
2213 return EINA_TRUE; 2282 types[++i] = "text/plain;charset=utf-8";
2283 }
2284
2285 if (format & ELM_SEL_FORMAT_MARKUP)
2286 types[++i] = "application/x-elementary-markup";
2287
2288 if (format & ELM_SEL_FORMAT_HTML)
2289 {
2290 types[++i] = "text/html";
2291 types[++i] = "text/html;charset=utf-8";
2292 }
2293
2294 if (i < 0) return EINA_FALSE;
2295
2296 ecore_wl_dnd_selection_set(ecore_wl_input_get(), types);
2297
2298 if (sel->selbuf) free(sel->selbuf);
2299 sel->buflen = buflen;
2300 sel->selbuf = strdup((char*)selbuf);
2301
2302 return EINA_TRUE;
2303 }
2214 } 2304 }
2305 else
2306 sel->selbuf = NULL;
2215 2307
2216 return EINA_FALSE; 2308 return EINA_FALSE;
2217} 2309}
2218 2310
2219static Eina_Bool 2311static Eina_Bool
2220_wl_elm_cnp_selection_get(Evas_Object *obj, Elm_Sel_Type selection, Elm_Sel_Format format __UNUSED__, Elm_Drop_Cb datacb __UNUSED__, void *udata __UNUSED__) 2312_wl_elm_cnp_selection_get(Evas_Object *obj, Elm_Sel_Type selection, Elm_Sel_Format format, Elm_Drop_Cb datacb, void *udata)
2221{ 2313{
2314 Ecore_Wl_Window *win;
2315 Wl_Cnp_Selection *sel = &wl_cnp_selection;
2316
2222 _wl_elm_cnp_init(); 2317 _wl_elm_cnp_init();
2223 2318
2224 /* For now, just avoid overlapped request */ 2319 win = elm_win_wl_window_get(obj);
2225 if (wl_cnp_selection.requestwidget) return EINA_FALSE; 2320
2321 if (sel->requestwidget)
2322 evas_object_event_callback_del_full(sel->requestwidget,
2323 EVAS_CALLBACK_DEL,
2324 _wl_sel_obj_del2, &wl_cnp_selection);
2325 sel->requestwidget = NULL;
2326
2327 sel->requestformat = format;
2328 sel->requestwidget = obj;
2329 sel->win = win;
2330 /* sel->request(win, ECORE_X_SELECTION_TARGET_TARGETS); */
2331 sel->datacb = datacb;
2332 sel->udata = udata;
2226 2333
2227 /* TODO: other EML_SEL_TYPE and ELM_SEL_FORMAT */ 2334 evas_object_event_callback_add(sel->requestwidget,
2228 if (ELM_SEL_TYPE_CLIPBOARD == selection) 2335 EVAS_CALLBACK_DEL, _wl_sel_obj_del2,
2336 &wl_cnp_selection);
2337
2338 if (selection == ELM_SEL_TYPE_CLIPBOARD)
2229 { 2339 {
2230 wl_cnp_selection.requestwidget = obj; 2340 const char *types[10] = {0, };
2231 evas_object_event_callback_add(wl_cnp_selection.requestwidget, EVAS_CALLBACK_DEL, 2341 int i = -1;
2232 _wl_sel_obj_del2, &wl_cnp_selection); 2342
2233 ecore_wl_dnd_selection_get(ecore_wl_input_get(), 2343 if (format & ELM_SEL_FORMAT_TEXT)
2234 "text/plain;charset=utf-8"); 2344 {
2345 types[++i] = "text/plain";
2346 types[++i] = "text/plain;charset=utf-8";
2347 }
2348
2349 if (format & ELM_SEL_FORMAT_MARKUP)
2350 types[++i] = "application/x-elementary-markup";
2351
2352 if (format & ELM_SEL_FORMAT_HTML)
2353 {
2354 types[++i] = "text/html";
2355 types[++i] = "text/html;charset=utf-8";
2356 }
2357
2358 if (i < 0) return EINA_FALSE;
2359
2360 ecore_wl_dnd_selection_get(ecore_wl_input_get(), *types);
2235 } 2361 }
2362
2236 return EINA_TRUE; 2363 return EINA_TRUE;
2237} 2364}
2238 2365
2366static void
2367_wl_elm_cnp_selection_loss_callback_set(Evas_Object *obj __UNUSED__, Elm_Sel_Type selection __UNUSED__, Elm_Selection_Loss_Cb func, const void *data)
2368{
2369 Wl_Cnp_Selection *sel = &wl_cnp_selection;
2370
2371 _wl_elm_cnp_init();
2372
2373 sel->loss_cb = func;
2374 sel->loss_data = (void *)data;
2375}
2376
2239static Eina_Bool 2377static Eina_Bool
2240_wl_elm_cnp_selection_clear(Evas_Object *obj EINA_UNUSED, Elm_Sel_Type selection) 2378_wl_elm_cnp_selection_clear(Evas_Object *obj, Elm_Sel_Type selection __UNUSED__)
2241{ 2379{
2380 Wl_Cnp_Selection *sel = &wl_cnp_selection;
2381
2242 _wl_elm_cnp_init(); 2382 _wl_elm_cnp_init();
2243 2383
2244 if (ELM_SEL_TYPE_CLIPBOARD == selection) 2384 if ((!sel->active) || (sel->widget != obj))
2245 { 2385 return EINA_TRUE;
2246 wl_cnp_selection.requestwidget = NULL; 2386
2247 if (wl_cnp_selection.selbuf) free(wl_cnp_selection.selbuf); 2387 if (sel->widget)
2248 wl_cnp_selection.buflen = 0; 2388 evas_object_event_callback_del_full(sel->widget,
2249 ecore_wl_dnd_selection_clear(ecore_wl_input_get()); 2389 EVAS_CALLBACK_DEL,
2250 } 2390 _wl_sel_obj_del, &wl_cnp_selection);
2391 if (sel->requestwidget)
2392 evas_object_event_callback_del_full(sel->requestwidget,
2393 EVAS_CALLBACK_DEL,
2394 _wl_sel_obj_del2, &wl_cnp_selection);
2395
2396 sel->widget = NULL;
2397 sel->requestwidget = NULL;
2398 sel->loss_cb = NULL;
2399 sel->loss_data = NULL;
2400
2401 sel->active = EINA_FALSE;
2402 ELM_SAFE_FREE(sel->selbuf, free);
2403 sel->buflen = 0;
2404 /* sel->clear(); */
2405 ecore_wl_dnd_selection_clear(ecore_wl_input_get());
2406
2251 return EINA_TRUE; 2407 return EINA_TRUE;
2252} 2408}
2253 2409
@@ -2290,17 +2446,78 @@ _wl_selection_receive(void *udata, int type __UNUSED__, void *event)
2290 { 2446 {
2291 if (!ev->done) 2447 if (!ev->done)
2292 { 2448 {
2293 /* TODO BUG: should never NEVER assume it's an elm_entry! */ 2449 if (sel->seltype == ELM_SEL_TYPE_XDND)
2294 _elm_entry_entry_paste(sel->requestwidget, ev->data); 2450 {
2451 Elm_Selection_Data sdata;
2452 Eina_List *l;
2453 Dropable *dropable;
2454
2455 EINA_LIST_FOREACH(drops, l, dropable)
2456 {
2457 if (dropable->obj == sel->requestwidget) break;
2458 dropable = NULL;
2459 }
2460
2461 if (dropable)
2462 {
2463 Dropable_Cbs *cbs;
2464
2465 sdata.x = savedtypes.x;
2466 sdata.y = savedtypes.y;
2467 sdata.format = ELM_SEL_FORMAT_TEXT;
2468 sdata.data = ev->data;
2469 sdata.len = ev->len;
2470 sdata.action = sel->action;
2471
2472 EINA_INLIST_FOREACH(dropable->cbs_list, cbs)
2473 if (cbs->dropcb)
2474 cbs->dropcb(cbs->dropdata, dropable->obj, &sdata);
2475
2476 goto end;
2477 }
2478 }
2479
2480 if (sel->datacb)
2481 {
2482 Elm_Selection_Data sdata;
2483
2484 sdata.x = sdata.y = 0;
2485 sdata.format = ELM_SEL_FORMAT_TEXT;
2486 sdata.data = ev->data;
2487 sdata.len = ev->len;
2488 sdata.action = sel->action;
2489 sel->datacb(sel->udata, sel->widget, &sdata);
2490 }
2491 else
2492 {
2493 char *stripstr, *mkupstr;
2494
2495 stripstr = malloc(ev->len + 1);
2496 if (!stripstr) goto end;
2497 strncpy(stripstr, (char *)ev->data, ev->len);
2498 stripstr[ev->len] = '\0';
2499 mkupstr = _elm_util_text_to_mkup((const char *)stripstr);
2500 /* TODO BUG: should never NEVER assume it's an elm_entry! */
2501 _elm_entry_entry_paste(sel->requestwidget, mkupstr);
2502 free(stripstr);
2503 free(mkupstr);
2504 }
2295 } 2505 }
2296 else 2506 else
2297 { 2507 {
2298 evas_object_event_callback_del_full(sel->requestwidget, EVAS_CALLBACK_DEL, 2508 evas_object_event_callback_del_full(sel->requestwidget,
2509 EVAS_CALLBACK_DEL,
2299 _wl_sel_obj_del2, sel); 2510 _wl_sel_obj_del2, sel);
2300 sel->requestwidget = NULL; 2511 sel->requestwidget = NULL;
2301 } 2512 }
2302 } 2513 }
2303 2514
2515end:
2516 if (sel->seltype == ELM_SEL_TYPE_XDND)
2517 {
2518 /* FIXME: Send Finished ?? */
2519 }
2520
2304 return ECORE_CALLBACK_PASS_ON; 2521 return ECORE_CALLBACK_PASS_ON;
2305} 2522}
2306 2523
@@ -3427,6 +3644,10 @@ elm_cnp_selection_loss_callback_set(Evas_Object *obj, Elm_Sel_Type selection,
3427 if (_x11_elm_widget_xwin_get(obj)) 3644 if (_x11_elm_widget_xwin_get(obj))
3428 _x11_elm_cnp_selection_loss_callback_set(obj, selection, func, data); 3645 _x11_elm_cnp_selection_loss_callback_set(obj, selection, func, data);
3429#endif 3646#endif
3647#ifdef HAVE_ELEMENTARY_WAYLAND
3648 if (elm_win_wl_window_get(obj))
3649 _wl_elm_cnp_selection_loss_callback_set(obj, selection, func, data);
3650#endif
3430 _local_elm_cnp_selection_loss_callback_set(obj, selection, func, data); 3651 _local_elm_cnp_selection_loss_callback_set(obj, selection, func, data);
3431} 3652}
3432 3653