Merge branch 'master' into svn_merge
[framework/uifw/elementary.git] / src / lib / elm_cbhm_helper.c
1 #include <Elementary.h>
2 #include "elm_priv.h"
3
4 #ifdef HAVE_ELEMENTARY_X
5 #include <X11/Xlib.h>
6 #include <X11/Xatom.h>
7 #endif
8
9 /**
10  * @defgroup CBHM_helper CBHM_helper
11  * @ingroup Elementary
12  *
13  * retrieving date from Clipboard History Manager
14  * CBHM_helper supports to get CBHM's contents
15  */
16
17 #define ATOM_CLIPBOARD_NAME "CLIPBOARD"
18 #define ATOM_CLIPBOARD_MANGER_NAME "CLIPBOARD_MANAGER"
19 #define CLIPBOARD_MANAGER_WINDOW_TITLE_STRING "X11_CLIPBOARD_HISTORY_MANAGER"
20 #define ATOM_CBHM_WINDOW_NAME "CBHM_XWIN"
21
22 #ifdef HAVE_ELEMENTARY_X
23 static Ecore_X_Display *cbhm_disp = NULL;
24 static Ecore_X_Window cbhm_win = None;
25 static Ecore_X_Window self_win = None;
26 #endif
27 static Eina_Bool init_flag = EINA_FALSE;
28
29 void _get_clipboard_window();
30 unsigned int _get_cbhm_serial_number();
31 void _search_clipboard_window(Ecore_X_Window w);
32 int _send_clipboard_events(char *cmd);
33 #ifdef HAVE_ELEMENTARY_X
34 int _get_clipboard_data(Atom datom, char **datomptr);
35 #endif
36
37 void _get_clipboard_window()
38 {
39 #ifdef HAVE_ELEMENTARY_X
40         Atom actual_type;
41         int actual_format;
42         unsigned long nitems, bytes_after;
43         unsigned char *prop_return = NULL;
44         Atom atomCbhmWin = XInternAtom(cbhm_disp, ATOM_CBHM_WINDOW_NAME, False);
45         if(Success == 
46            XGetWindowProperty(cbhm_disp, DefaultRootWindow(cbhm_disp), atomCbhmWin, 
47                                                   0, sizeof(Ecore_X_Window), False, XA_WINDOW, 
48                                                   &actual_type, &actual_format, &nitems, &bytes_after, &prop_return) && 
49            prop_return)
50         {
51                 cbhm_win = *(Ecore_X_Window*)prop_return;
52                 XFree(prop_return);
53                 fprintf(stderr, "## find clipboard history manager at root\n");
54         }
55 #endif
56 }
57
58 unsigned int _get_cbhm_serial_number()
59 {
60         unsigned int senum = 0;
61 #ifdef HAVE_ELEMENTARY_X
62         Atom actual_type;
63         int actual_format;
64         unsigned long nitems, bytes_after;
65         unsigned char *prop_return = NULL;
66         Atom atomCbhmSN = XInternAtom(cbhm_disp, "CBHM_SERIAL_NUMBER", False);
67
68         // FIXME : is it really needed?
69         XSync(cbhm_disp, EINA_FALSE);
70
71         if(Success == 
72            XGetWindowProperty(cbhm_disp, cbhm_win, atomCbhmSN, 
73                                                   0, sizeof(Ecore_X_Window), False, XA_INTEGER, 
74                                                   &actual_type, &actual_format, &nitems, &bytes_after, &prop_return) && 
75            prop_return)
76         {
77                 senum = *(unsigned int*)prop_return;
78                 XFree(prop_return);
79         }
80         fprintf(stderr, "## chbm_serial = %d\n", senum);
81 #endif
82         return senum;
83 }
84
85 void _search_clipboard_window(Ecore_X_Window w)
86 {
87 #ifdef HAVE_ELEMENTARY_X
88     // Get the PID for the current Window.
89         Atom atomWMName = XInternAtom(cbhm_disp, "_NET_WM_NAME", False);
90         Atom atomUTF8String = XInternAtom(cbhm_disp, "UTF8_STRING", False);
91         Atom type;
92         int format;
93         unsigned long nitems;
94         unsigned long bytes_after;
95         unsigned long nsize = 0;
96         unsigned char *propName = 0;
97         if(Success == 
98            XGetWindowProperty(cbhm_disp, w, atomWMName, 0, (long)nsize, False,
99                                                   atomUTF8String, &type, &format, &nitems, &bytes_after, &propName))
100
101         {
102                 if(propName != 0)
103                 {
104                         if (strcmp((const char *)CLIPBOARD_MANAGER_WINDOW_TITLE_STRING,(const char *)propName) == 0)
105                                 cbhm_win = w;
106                         XFree(propName);
107                 }
108         }
109
110     // Recurse into child windows.
111         Window wroot;
112         Window wparent;
113         Window *wchild;
114         unsigned nchildren;
115         int i;
116         if(0 != XQueryTree(cbhm_disp, w, &wroot, &wparent, &wchild, &nchildren))
117         {
118                 for(i = 0; i < nchildren; i++)
119                         _search_clipboard_window(wchild[i]);
120         }
121 #endif
122 }
123
124 int _send_clipboard_events(char *cmd)
125 {
126         if (cmd == NULL)
127                 return -1;
128
129 #ifdef HAVE_ELEMENTARY_X
130         Atom atomCBHM_MSG = XInternAtom(cbhm_disp, "CBHM_MSG", False);
131
132         XClientMessageEvent m;
133         memset(&m, sizeof(m), 0);
134         m.type = ClientMessage;
135         m.display = cbhm_disp;
136         m.window = self_win;
137         m.message_type = atomCBHM_MSG;
138         m.format = 8;
139         sprintf(m.data.b, "%s", cmd);
140
141         XSendEvent(cbhm_disp, cbhm_win, False, NoEventMask, (XEvent*)&m);
142 #endif
143         return 0;
144 }
145
146 #ifdef HAVE_ELEMENTARY_X
147 int _get_clipboard_data(Atom datom, char **datomptr)
148 {
149 //      Atom atomUTF8String = XInternAtom(cbhm_disp, "UTF8_STRING", False);
150         Atom type;
151         int format;
152         unsigned long nitems;
153         unsigned long nsize;
154         unsigned char *propname = NULL;
155
156         // FIXME : is it really needed?
157         XSync(cbhm_disp, EINA_FALSE);
158
159         if (Success == 
160                 XGetWindowProperty(cbhm_disp, self_win, datom, 0, 0, False,
161                                                    AnyPropertyType, &type, &format, &nitems, &nsize, &propname))
162                 XFree(propname);
163         else
164                 return -1;
165
166 /*
167         fprintf(stderr, "## format = %d\n", format);
168         fprintf(stderr, "## nsize = %d\n", nsize);
169 */
170
171         if (format != 8)
172                 return -1;
173
174         if (Success == 
175                 XGetWindowProperty(cbhm_disp, self_win, datom, 0, (long)nsize, False,
176                                                    AnyPropertyType, &type, &format, &nitems, &nsize, &propname))
177         {
178                 if (nsize != 0)
179                         XGetWindowProperty(cbhm_disp, self_win, datom, 0, (long)nsize, False,
180                                                            AnyPropertyType, &type, &format, &nitems, &nsize, &propname);
181
182                 if(propname != NULL)
183                 {
184 //                      fprintf(stderr, "## get data(0x%x) : %s\n", propname, propname);
185 //                      fprintf(stderr, "## after nsize = %d\n", nsize);
186                         *datomptr = (char*)propname;
187 //                      XFree(propName);
188                 }
189
190                 XDeleteProperty(cbhm_disp, self_win, datom);
191                 XFlush(cbhm_disp);
192         }
193
194         if (propname != NULL)
195                 return 0;
196
197         *datomptr = NULL;
198         return -1;
199 }
200 #endif
201
202 void free_clipboard_data(char *dptr)
203 {
204 #ifdef HAVE_ELEMENTARY_X
205         XFree(dptr);
206         return;
207 #endif
208 }
209
210
211 /**
212  * initalizing CBHM_helper
213  *
214  * @param self The self window object which receive events
215  * @return return TRUE or FALSE if it cannot be created
216  *
217  * @ingroup CBHM_helper
218  */
219 EAPI Eina_Bool 
220 elm_cbhm_helper_init(Evas_Object *self)
221 {
222         init_flag = EINA_FALSE;
223
224 #ifdef HAVE_ELEMENTARY_X
225         cbhm_disp = ecore_x_display_get();
226         if (cbhm_disp == NULL)
227                 return init_flag;
228         if (cbhm_win == None)
229                 _get_clipboard_window();
230         if (cbhm_win == None)
231                 _search_clipboard_window(DefaultRootWindow(cbhm_disp));
232         if (self_win == None)
233                 self_win = ecore_evas_software_x11_window_get(ecore_evas_ecore_evas_get(evas_object_evas_get(self)));
234    
235         if (cbhm_disp && cbhm_win && self_win)
236                 init_flag = EINA_TRUE;
237 #endif
238         return init_flag;
239 }
240
241 /**
242  * getting serial number of CBHM
243  *
244  * @return return serial number of clipboard history manager
245  *
246  * @ingroup CBHM_helper
247  */
248 EAPI unsigned int 
249 elm_cbhm_get_serial_number()
250 {
251         if (init_flag == EINA_FALSE)
252                 return 0;
253
254         unsigned int num = 0;
255         num = _get_cbhm_serial_number();
256         return num;
257 }
258
259 /**
260  * getting count of CBHM's contents
261  *
262  * @return return count of history contents
263  *
264  * @ingroup CBHM_helper
265  */
266 EAPI int 
267 elm_cbhm_get_count()
268 {
269         if (init_flag == EINA_FALSE)
270                 return -1;
271
272         char *retptr = NULL;
273         int count = 0;
274
275         _send_clipboard_events("get count");
276
277 #ifdef HAVE_ELEMENTARY_X
278         Atom atomCBHM_cCOUNT = XInternAtom(cbhm_disp, "CBHM_cCOUNT", False);
279
280         _get_clipboard_data(atomCBHM_cCOUNT, &retptr);
281 #endif
282
283         if (retptr != NULL)
284         {
285                 fprintf(stderr, "## c get retptr : %s\n", retptr);
286                 count = atoi(retptr);
287
288                 free_clipboard_data(retptr);
289                 retptr = NULL;
290         }
291
292         return count;
293 }
294
295 /**
296  * getting raw data of CBHM's contents
297  *
298  * @return return raw data of history contents
299  *
300  * @ingroup CBHM_helper
301  */
302 EAPI int 
303 elm_cbhm_get_raw_data()
304 {
305         if (init_flag == EINA_FALSE)
306                 return -1;
307
308         char *retptr = NULL;
309
310         _send_clipboard_events("get raw");
311
312 #ifdef HAVE_ELEMENTARY_X
313         Atom atomCBHM_cRAW = XInternAtom(cbhm_disp, "CBHM_cRAW", False);
314
315         _get_clipboard_data(atomCBHM_cRAW, &retptr);
316 #endif
317
318         if (retptr != NULL)
319         {
320                 free_clipboard_data(retptr);
321                 retptr = NULL;
322         }
323
324         return 0;
325 }
326
327 /**
328  * sending raw command to CBHM
329  *
330  * @return void
331  *
332  * @ingroup CBHM_helper
333  */
334 EAPI void
335 elm_cbhm_send_raw_data(char *cmd)
336 {
337         if (init_flag == EINA_FALSE)
338                 return;
339
340         if (cmd == NULL)
341                 return;
342
343         _send_clipboard_events(cmd);
344         fprintf(stderr, "## cbhm - send raw cmd = %s\n", cmd);
345
346         return;
347 }
348
349 /**
350  * getting data by history position of CBHM's contents
351  * 0 is current content.
352  *
353  * @return return data pointer of position of history contents
354  *
355  * @ingroup CBHM_helper
356  */
357 EAPI int
358 elm_cbhm_get_data_by_position(int pos, char **dataptr)
359 {
360         if (init_flag == EINA_FALSE)
361                 return -1;
362
363         char reqbuf[16];
364         int ret = 0;
365         sprintf(reqbuf, "get #%d", pos);
366
367         _send_clipboard_events(reqbuf);
368
369         sprintf(reqbuf, "CBHM_c%d", pos);
370
371 #ifdef HAVE_ELEMENTARY_X
372         Atom atomCBHM_cPOS = XInternAtom(cbhm_disp, reqbuf, False);
373
374         ret = _get_clipboard_data(atomCBHM_cPOS, dataptr);
375 #endif
376
377         if (ret >= 0 && *dataptr != NULL)
378         {
379 //              fprintf(stderr, "## d get retptr : %s\n", *dataptr);
380 //              fprintf(stderr, "## dptr = 0x%x\n", *dataptr);
381
382                 return 0;
383         }
384
385         return -1;
386 }
387
388 /**
389  * free data by history position of CBHM's contents
390  *
391  * @return None
392  *
393  * @ingroup CBHM_helper
394  */
395 EAPI void
396 elm_cbhm_free_data(char *dptr)
397 {
398         if (dptr != NULL)
399                 free_clipboard_data(dptr);
400 }