Support dlog logging system
[platform/upstream/enlightenment.git] / src / bin / e_info_server.c
1 #define E_COMP_WL
2 #include "e.h"
3 #include "e_info_server.h"
4 #include <tbm_bufmgr.h>
5 #include <tbm_surface.h>
6 #include <tdm_helper.h>
7 #ifdef HAVE_WAYLAND_ONLY
8 #include <wayland-tbm-server.h>
9 #include "e_comp_wl.h"
10 void wl_map_for_each(struct wl_map *map, void *func, void *data);
11 #endif
12 #ifdef HAVE_HWC
13 #include "e_comp_hwc.h"
14 #endif
15
16 #define BUS "org.enlightenment.wm"
17 #define PATH "/org/enlightenment/wm"
18 #define IFACE "org.enlightenment.wm.info"
19
20 E_API int E_EVENT_INFO_ROTATION_MESSAGE = -1;
21
22 typedef struct _E_Info_Server
23 {
24    Eldbus_Connection *conn;
25    Eldbus_Service_Interface *iface;
26 } E_Info_Server;
27
28 typedef struct _E_Info_Transform
29 {
30    E_Client         *ec;
31    E_Util_Transform *transform;
32    int               id;
33    int               enable;
34 } E_Info_Transform;
35
36 static E_Info_Server e_info_server;
37 static Eina_List    *e_info_transform_list = NULL;
38
39 static Eina_List    *e_info_dump_hdlrs;
40 static char         *e_info_dump_path;
41 static int           e_info_dump_running;
42 static int           e_info_dump_count;
43
44 #define VALUE_TYPE_FOR_TOPVWINS "uuisiiiiibbiibbis"
45 #define VALUE_TYPE_REQUEST_RESLIST "ui"
46 #define VALUE_TYPE_REPLY_RESLIST "ssi"
47 #define VALUE_TYPE_FOR_INPUTDEV "ssi"
48
49 static E_Info_Transform *_e_info_transform_new(E_Client *ec, int id, int enable, int x, int y, int sx, int sy, int degree, int keep_ratio);
50 static E_Info_Transform *_e_info_transform_find(E_Client *ec, int id);
51 static void              _e_info_transform_set(E_Info_Transform *transform, int enable, int x, int y, int sx, int sy, int degree, int keep_ratio);
52 static void              _e_info_transform_del(E_Info_Transform *transform);
53 static void              _e_info_transform_del_with_id(E_Client *ec, int id);
54
55 static void
56 _msg_clients_append(Eldbus_Message_Iter *iter)
57 {
58    Eldbus_Message_Iter *array_of_ec;
59    E_Client *ec;
60    Evas_Object *o;
61
62    eldbus_message_iter_arguments_append(iter, "a("VALUE_TYPE_FOR_TOPVWINS")", &array_of_ec);
63
64    // append clients.
65    for (o = evas_object_top_get(e_comp->evas); o; o = evas_object_below_get(o))
66      {
67         Eldbus_Message_Iter* struct_of_ec;
68         Ecore_Window win;
69         uint32_t res_id = 0;
70         pid_t pid = -1;
71         char layer_name[32];
72         int hwc = -1;
73
74         ec = evas_object_data_get(o, "E_Client");
75         if (!ec) continue;
76         if (e_client_util_ignored_get(ec)) continue;
77
78         win = e_client_util_win_get(ec);
79         e_comp_layer_name_get(ec->layer, layer_name, sizeof(layer_name));
80
81         if (ec->pixmap)
82           res_id = e_pixmap_res_id_get(ec->pixmap);
83
84         pid = ec->netwm.pid;
85 #ifdef HAVE_WAYLAND_ONLY
86         if (pid <= 0)
87           {
88              if (ec->comp_data)
89                {
90                   E_Comp_Wl_Client_Data *cdata = (E_Comp_Wl_Client_Data*)ec->comp_data;
91                   if (cdata->surface)
92                     wl_client_get_credentials(wl_resource_get_client(cdata->surface), &pid, NULL, NULL);
93                }
94           }
95 #endif
96         if (e_comp->hwc)
97           {
98              // TODO: print plane number
99              if (!e_comp->nocomp_ec)
100                hwc = 1; // comp mode
101              else if (e_comp->nocomp_ec == ec)
102                hwc = 2; // a client occupied scanout buff
103              else
104                hwc = 0;
105           }
106
107         eldbus_message_iter_arguments_append(array_of_ec, "("VALUE_TYPE_FOR_TOPVWINS")", &struct_of_ec);
108
109         eldbus_message_iter_arguments_append
110            (struct_of_ec, VALUE_TYPE_FOR_TOPVWINS,
111             win,
112             res_id,
113             pid,
114             e_client_util_name_get(ec) ?: "NO NAME",
115             ec->x, ec->y, ec->w, ec->h, ec->layer,
116             ec->visible, ec->argb, ec->visibility.opaque, ec->visibility.obscured, ec->iconic, ec->focused, hwc, layer_name);
117
118         eldbus_message_iter_container_close(array_of_ec, struct_of_ec);
119      }
120
121    eldbus_message_iter_container_close(iter, array_of_ec);
122 }
123
124 /* Method Handlers */
125 static Eldbus_Message *
126 _e_info_server_cb_window_info_get(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
127 {
128    Eldbus_Message *reply = eldbus_message_method_return_new(msg);
129
130    _msg_clients_append(eldbus_message_iter_get(reply));
131
132    return reply;
133 }
134
135 static void
136 _input_msg_clients_append(Eldbus_Message_Iter *iter)
137 {
138    Eldbus_Message_Iter *array_of_input;
139    Eina_List *l;
140    E_Comp_Wl_Data *cdata;
141    E_Comp_Wl_Input_Device *dev;
142
143    eldbus_message_iter_arguments_append(iter, "a("VALUE_TYPE_FOR_INPUTDEV")", &array_of_input);
144
145    cdata = e_comp->wl_comp_data;
146    EINA_LIST_FOREACH(cdata->input_device_manager.device_list, l, dev)
147      {
148         Eldbus_Message_Iter *struct_of_input;
149
150         eldbus_message_iter_arguments_append(array_of_input, "("VALUE_TYPE_FOR_INPUTDEV")", &struct_of_input);
151
152         eldbus_message_iter_arguments_append
153                      (struct_of_input, VALUE_TYPE_FOR_INPUTDEV,
154                       dev->name, dev->identifier, dev->capability);
155
156         eldbus_message_iter_container_close(array_of_input, struct_of_input);
157      }
158    eldbus_message_iter_container_close(iter, array_of_input);
159 }
160
161
162 static Eldbus_Message *
163 _e_info_server_cb_input_device_info_get(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
164 {
165    Eldbus_Message *reply = eldbus_message_method_return_new(msg);
166
167    _input_msg_clients_append(eldbus_message_iter_get(reply));
168
169    return reply;
170 }
171
172 static void
173 _msg_connected_clients_append(Eldbus_Message_Iter *iter)
174 {
175    Eldbus_Message_Iter *array_of_ec;
176    E_Client *ec;
177    Evas_Object *o;
178
179    eldbus_message_iter_arguments_append(iter, "a(ss)", &array_of_ec);
180
181    Eina_List *l;
182    E_Comp_Connected_Client_Info *cinfo;
183
184
185    Eldbus_Message_Iter* struct_of_ec;
186
187 #define __CONNECTED_CLIENTS_ARG_APPEND_TYPE(title, str, x...) ({                           \
188                                                                char __temp[128] = {0,};                                                     \
189                                                                snprintf(__temp, sizeof(__temp), str, ##x);                                  \
190                                                                eldbus_message_iter_arguments_append(array_of_ec, "(ss)", &struct_of_ec);    \
191                                                                eldbus_message_iter_arguments_append(struct_of_ec, "ss", (title), (__temp)); \
192                                                                eldbus_message_iter_container_close(array_of_ec, struct_of_ec);})
193
194    EINA_LIST_FOREACH(e_comp->connected_clients, l, cinfo)
195      {
196         __CONNECTED_CLIENTS_ARG_APPEND_TYPE("[Connected Clients]", "name:%20s pid:%3d uid:%3d gid:%3d", cinfo->name ?: "NO_NAME", cinfo->pid, cinfo->uid, cinfo->gid);
197         for (o = evas_object_top_get(e_comp->evas); o; o = evas_object_below_get(o))
198           {
199              Ecore_Window win;
200              uint32_t res_id = 0;
201              pid_t pid = -1;
202
203              ec = evas_object_data_get(o, "E_Client");
204              if (!ec) continue;
205              if (e_client_util_ignored_get(ec)) continue;
206
207              win = e_client_util_win_get(ec);
208
209              if (ec->pixmap)
210                res_id = e_pixmap_res_id_get(ec->pixmap);
211 #ifdef HAVE_WAYLAND_ONLY
212              if (ec->comp_data)
213                {
214                   E_Comp_Wl_Client_Data *cdata = (E_Comp_Wl_Client_Data*)ec->comp_data;
215                   if (cdata->surface)
216                     wl_client_get_credentials(wl_resource_get_client(cdata->surface), &pid, NULL, NULL);
217                }
218 #endif
219              if (cinfo->pid == pid)
220                {
221                   __CONNECTED_CLIENTS_ARG_APPEND_TYPE("[E_Client Info]", "win:0x%08x res_id:%5d, name:%20s, geo:(%4d, %4d, %4dx%4d), layer:%5d, visible:%d, argb:%d",
222                                                       win, res_id, e_client_util_name_get(ec) ?: "NO_NAME", ec->x, ec->y, ec->w, ec->h, ec->layer, ec->visible, ec->argb);
223                }
224           }
225      }
226
227    eldbus_message_iter_container_close(iter, array_of_ec);
228 }
229
230 static Eldbus_Message *
231 _e_info_server_cb_connected_clients_get(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
232 {
233    Eldbus_Message *reply = eldbus_message_method_return_new(msg);
234
235    _msg_connected_clients_append(eldbus_message_iter_get(reply));
236
237    return reply;
238 }
239
240 #define wl_client_for_each(client, list)     \
241    for (client = 0, client = wl_client_from_link((list)->next);   \
242         wl_client_get_link(client) != (list);                     \
243         client = wl_client_from_link(wl_client_get_link(client)->next))
244
245 static int resurceCnt = 0;
246
247 static void
248 _e_info_server_get_resource(void *element, void *data)
249 {
250    struct wl_resource *resource = element;
251    Eldbus_Message_Iter* array_of_res= data;
252    Eldbus_Message_Iter* struct_of_res;
253
254    eldbus_message_iter_arguments_append(array_of_res, "("VALUE_TYPE_REPLY_RESLIST")", &struct_of_res);
255    eldbus_message_iter_arguments_append(struct_of_res, VALUE_TYPE_REPLY_RESLIST, "[resource]", wl_resource_get_name(resource), wl_resource_get_id(resource));
256    eldbus_message_iter_container_close(array_of_res, struct_of_res);
257    resurceCnt++;
258 }
259
260 static void
261 _msg_clients_res_list_append(Eldbus_Message_Iter *iter, uint32_t mode, int id)
262 {
263    Eldbus_Message_Iter *array_of_res;
264
265    struct wl_list * client_list;
266    struct wl_client *client;
267    struct wl_map *res_objs;
268    //E_Comp_Data *cdata;
269    E_Comp_Wl_Data *cdata;
270    int pid = -1;
271
272    enum {
273    DEFAULT_SUMMARY,
274    TREE,
275    PID} type = mode;
276
277    eldbus_message_iter_arguments_append(iter, "a("VALUE_TYPE_REPLY_RESLIST")", &array_of_res);
278
279    if (!e_comp) return;
280    if (!(cdata = e_comp->wl_comp_data)) return;
281    if (!cdata->wl.disp) return;
282
283    client_list = wl_display_get_client_list(cdata->wl.disp);
284
285    wl_client_for_each(client, client_list)
286      {
287         Eldbus_Message_Iter* struct_of_res;
288
289         wl_client_get_credentials(client, &pid, NULL, NULL);
290
291         if ((type == PID) && (pid != id)) continue;
292
293         eldbus_message_iter_arguments_append(array_of_res, "("VALUE_TYPE_REPLY_RESLIST")", &struct_of_res);
294
295         eldbus_message_iter_arguments_append(struct_of_res, VALUE_TYPE_REPLY_RESLIST, "[client]", "pid", pid);
296         eldbus_message_iter_container_close(array_of_res, struct_of_res);
297
298         resurceCnt = 0;
299         res_objs = wl_client_get_resources(client);
300         wl_map_for_each(res_objs, _e_info_server_get_resource, array_of_res);
301
302         eldbus_message_iter_arguments_append(array_of_res, "("VALUE_TYPE_REPLY_RESLIST")", &struct_of_res);
303         eldbus_message_iter_arguments_append(struct_of_res, VALUE_TYPE_REPLY_RESLIST, "[count]", "resurceCnt", resurceCnt);
304         eldbus_message_iter_container_close(array_of_res, struct_of_res);
305      }
306    eldbus_message_iter_container_close(iter, array_of_res);
307 }
308
309 static Eldbus_Message *
310 _e_info_server_cb_res_lists_get(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
311 {
312    Eldbus_Message *reply = eldbus_message_method_return_new(msg);
313    uint32_t mode = 0;
314    int pid = -1;
315
316    if (!eldbus_message_arguments_get(msg, VALUE_TYPE_REQUEST_RESLIST, &mode, &pid))
317      {
318         ERR("Error getting arguments.");
319         return reply;
320      }
321
322    _msg_clients_res_list_append(eldbus_message_iter_get(reply), mode, pid);
323
324    return reply;
325 }
326
327 static void
328 _msg_window_prop_client_append(Eldbus_Message_Iter *iter, E_Client *target_ec)
329 {
330    Eldbus_Message_Iter* struct_of_ec;
331    pid_t pid = -1;
332    char win_resid[16] = {0,};
333    char char_True[] = "TRUE";
334    char char_False[] = "FALSE";
335    char layer_name[48] = {0,};
336    char layer[64] = {0,};
337    char transients[128] = {0,};
338    char shape_rects[128] = {0,};
339    char shape_input[128] = {0,};
340
341    if (!target_ec) return;
342
343    if (target_ec->pixmap)
344       snprintf(win_resid, sizeof(win_resid), "%d", e_pixmap_res_id_get(target_ec->pixmap));
345
346    e_comp_layer_name_get(target_ec->layer, layer_name, sizeof(layer_name));
347    snprintf(layer, sizeof(layer), "[%d, %s]",  target_ec->layer, layer_name);
348
349    if (target_ec->transients)
350      {
351         E_Client *child;
352         const Eina_List *l;
353
354         EINA_LIST_FOREACH(target_ec->transients, l, child)
355           {
356              char temp[16];
357              snprintf(temp, sizeof(temp), "0x%x", e_client_util_win_get(child));
358              strncat(transients, temp, sizeof(transients) - strlen(transients));
359           }
360      }
361
362    if (target_ec->shape_rects && target_ec->shape_rects_num > 0)
363      {
364         int i = 0;
365         for (i = 0 ; i < target_ec->shape_rects_num ; ++i)
366           {
367              char temp[32];
368              snprintf(temp, sizeof(temp), "[%d,%d,%d,%d] ", target_ec->shape_rects[i].x, target_ec->shape_rects[i].y,
369                       target_ec->shape_rects[i].w, target_ec->shape_rects[i].h);
370              strncat(shape_rects, temp, sizeof(shape_rects) - strlen(shape_rects));
371           }
372      }
373
374    if (target_ec->shape_input_rects && target_ec->shape_input_rects_num > 0)
375      {
376         int i = 0;
377         for (i = 0 ; i < target_ec->shape_input_rects_num ; ++i)
378           {
379              char temp[32];
380              snprintf(temp, sizeof(temp), "[%d,%d,%d,%d] ", target_ec->shape_input_rects[i].x, target_ec->shape_input_rects[i].y,
381                       target_ec->shape_input_rects[i].w, target_ec->shape_input_rects[i].h);
382              strncat(shape_input, temp, sizeof(shape_input) - strlen(shape_input));
383           }
384      }
385
386 #ifdef HAVE_WAYLAND_ONLY
387    if (target_ec->comp_data)
388      {
389
390         E_Comp_Wl_Client_Data *cdata = (E_Comp_Wl_Client_Data*)target_ec->comp_data;
391         if (cdata->surface)
392           {
393              wl_client_get_credentials(wl_resource_get_client(cdata->surface), &pid, NULL, NULL);
394           }
395      }
396 #endif
397
398 #define __WINDOW_PROP_ARG_APPEND(title, value) ({                                    \
399                                                 eldbus_message_iter_arguments_append(iter, "(ss)", &struct_of_ec);    \
400                                                 eldbus_message_iter_arguments_append(struct_of_ec, "ss", (title), (value));  \
401                                                 eldbus_message_iter_container_close(iter, struct_of_ec);})
402
403 #define __WINDOW_PROP_ARG_APPEND_TYPE(title, str, x...) ({                           \
404                                                          char __temp[128] = {0,};                                                     \
405                                                          snprintf(__temp, sizeof(__temp), str, ##x);                                  \
406                                                          eldbus_message_iter_arguments_append(iter, "(ss)", &struct_of_ec);    \
407                                                          eldbus_message_iter_arguments_append(struct_of_ec, "ss", (title), (__temp)); \
408                                                          eldbus_message_iter_container_close(iter, struct_of_ec);})
409
410    __WINDOW_PROP_ARG_APPEND("[WINDOW PROP]", "[WINDOW PROP]");
411    __WINDOW_PROP_ARG_APPEND_TYPE("Window_ID", "0x%x", e_client_util_win_get(target_ec));
412    __WINDOW_PROP_ARG_APPEND_TYPE("PID", "%d", pid);
413    __WINDOW_PROP_ARG_APPEND("ResourceID", win_resid);
414    __WINDOW_PROP_ARG_APPEND("Window_Name", e_client_util_name_get(target_ec) ?: "NO NAME");
415    __WINDOW_PROP_ARG_APPEND("Role", target_ec->icccm.window_role ?: "NO ROLE");
416    __WINDOW_PROP_ARG_APPEND_TYPE("Geometry", "[%d, %d, %d, %d]", target_ec->x, target_ec->y, target_ec->w, target_ec->h);
417    __WINDOW_PROP_ARG_APPEND_TYPE("ParentWindowID", "0x%x", target_ec->parent ? e_client_util_win_get(target_ec->parent) : 0);
418    __WINDOW_PROP_ARG_APPEND("Transients", transients);
419    __WINDOW_PROP_ARG_APPEND("Shape_rects", shape_rects);
420    __WINDOW_PROP_ARG_APPEND("Shape_input", shape_input);
421    __WINDOW_PROP_ARG_APPEND("Layer", layer);
422    __WINDOW_PROP_ARG_APPEND("Visible",  target_ec->visible ? char_True : char_False);
423    __WINDOW_PROP_ARG_APPEND("32bit",  target_ec->argb ? char_True : char_False);
424    __WINDOW_PROP_ARG_APPEND("Hidden", target_ec->hidden ? char_True : char_False);
425    __WINDOW_PROP_ARG_APPEND("Moving", target_ec->moving ? char_True : char_False);
426    __WINDOW_PROP_ARG_APPEND("Focused", target_ec->focused ? char_True : char_False);
427    __WINDOW_PROP_ARG_APPEND("Iconic", target_ec->iconic ? char_True : char_False);
428    __WINDOW_PROP_ARG_APPEND("Sticky", target_ec->sticky ? char_True : char_False);
429    __WINDOW_PROP_ARG_APPEND("Urgent", target_ec->urgent ? char_True : char_False);
430    __WINDOW_PROP_ARG_APPEND("Fullscreen", target_ec->fullscreen ? char_True : char_False);
431    __WINDOW_PROP_ARG_APPEND("Re_manage", target_ec->re_manage ? char_True : char_False);
432    __WINDOW_PROP_ARG_APPEND("Take_focus", target_ec->take_focus ? char_True : char_False);
433    __WINDOW_PROP_ARG_APPEND("Want_focus", target_ec->want_focus ? char_True : char_False);
434    __WINDOW_PROP_ARG_APPEND_TYPE("E_Maximize_Policy", "0x%x", target_ec->maximized);
435    __WINDOW_PROP_ARG_APPEND_TYPE("E_FullScreen_Policy", "%d", target_ec->fullscreen_policy);
436    __WINDOW_PROP_ARG_APPEND_TYPE("E_Transient_Policy", "%d", target_ec->transient_policy);
437    __WINDOW_PROP_ARG_APPEND("Override", target_ec->override ? char_True : char_False);
438    __WINDOW_PROP_ARG_APPEND("Input_only", target_ec->input_only ? char_True : char_False);
439    __WINDOW_PROP_ARG_APPEND("Dialog", target_ec->dialog ? char_True : char_False);
440    __WINDOW_PROP_ARG_APPEND("Tooltip", target_ec->tooltip ? char_True : char_False);
441    __WINDOW_PROP_ARG_APPEND("Redirected", target_ec->redirected ? char_True : char_False);
442    __WINDOW_PROP_ARG_APPEND("Unredirected_single", target_ec->unredirected_single ? char_True : char_False);
443    __WINDOW_PROP_ARG_APPEND("Shape_changed", target_ec->shape_changed ? char_True : char_False);
444    __WINDOW_PROP_ARG_APPEND("Layer_block", target_ec->layer_block ? char_True : char_False);
445    __WINDOW_PROP_ARG_APPEND("Ignored", target_ec->ignored ? char_True : char_False);
446    __WINDOW_PROP_ARG_APPEND("No_shape_cut", target_ec->no_shape_cut ? char_True : char_False);
447    __WINDOW_PROP_ARG_APPEND("Maximize_override", target_ec->maximize_override ? char_True : char_False);
448    __WINDOW_PROP_ARG_APPEND("Transformed", target_ec->transformed ? char_True : char_False);
449    __WINDOW_PROP_ARG_APPEND_TYPE("Ignore_first_unmap", "%c", target_ec->ignore_first_unmap);
450    __WINDOW_PROP_ARG_APPEND_TYPE("Transform_count", "%d", e_client_transform_core_transform_count_get(target_ec));
451    if (e_client_transform_core_transform_count_get(target_ec) > 0)
452      {
453         int i;
454         int count = e_client_transform_core_transform_count_get(target_ec);
455
456         __WINDOW_PROP_ARG_APPEND(" ", "[id] [move] [scale] [rotation] [keep_ratio]");
457         for (i = 0 ; i < count ; ++i)
458           {
459              double dx, dy, dsx, dsy, drz;
460              int x, y, rz;
461              int keep_ratio;
462
463              E_Util_Transform *transform = e_client_transform_core_transform_get(target_ec, i);
464              if (!transform) continue;
465
466              e_util_transform_move_get(transform, &dx, &dy, NULL);
467              e_util_transform_scale_get(transform, &dsx, &dsy, NULL);
468              e_util_transform_rotation_get(transform, NULL, NULL, &drz);
469              keep_ratio = e_util_transform_keep_ratio_get(transform);
470
471              x = (int)(dx + 0.5);
472              y = (int)(dy + 0.5);
473              rz = (int)(drz + 0.5);
474
475              __WINDOW_PROP_ARG_APPEND_TYPE("Transform", "[%d] [%d, %d] [%2.1f, %2.1f] [%d] [%d]", i, x, y, dsx, dsy, rz, keep_ratio);
476           }
477      }
478 #undef __WINDOW_PROP_ARG_APPEND
479 #undef __WINDOW_PROP_ARG_APPEND_TYPE
480 }
481
482 static void
483 _msg_window_prop_append(Eldbus_Message_Iter *iter, uint32_t mode, const char *value)
484 {
485    const static int WINDOW_ID_MODE = 0;
486    const static int WINDOW_PID_MODE = 1;
487    const static int WINDOW_NAME_MODE = 2;
488
489    Eldbus_Message_Iter *array_of_ec;
490    E_Client *ec;
491    Evas_Object *o;
492    int32_t value_number = 0;
493
494    eldbus_message_iter_arguments_append(iter, "a(ss)", &array_of_ec);
495
496    if (mode == WINDOW_ID_MODE || mode == WINDOW_PID_MODE)
497      {
498         if (!value) value_number = 0;
499         else
500           {
501              if (strlen(value) >= 2 && value[0] == '0' && value[1] == 'x')
502                 sscanf(value, "%x", &value_number);
503              else
504                 sscanf(value, "%d", &value_number);
505           }
506      }
507
508    for (o = evas_object_top_get(e_comp->evas); o; o = evas_object_below_get(o))
509      {
510         ec = evas_object_data_get(o, "E_Client");
511         if (!ec) continue;
512
513         if (mode == WINDOW_ID_MODE)
514           {
515              Ecore_Window win = e_client_util_win_get(ec);
516
517              if (win == value_number)
518                {
519                   _msg_window_prop_client_append(array_of_ec, ec);
520                   break;
521                }
522           }
523         else if (mode == WINDOW_PID_MODE)
524           {
525              pid_t pid = -1;
526 #ifdef HAVE_WAYLAND_ONLY
527              if (ec->comp_data)
528                {
529                   E_Comp_Wl_Client_Data *cdata = (E_Comp_Wl_Client_Data*)ec->comp_data;
530                   if (cdata->surface)
531                     {
532                        wl_client_get_credentials(wl_resource_get_client(cdata->surface), &pid, NULL, NULL);
533                     }
534                }
535 #endif
536              if (pid == value_number)
537                {
538                   _msg_window_prop_client_append(array_of_ec, ec);
539                }
540           }
541         else if (mode == WINDOW_NAME_MODE)
542           {
543              const char *name = e_client_util_name_get(ec) ?: "NO NAME";
544
545              if (name != NULL && value != NULL)
546                {
547                   const char *find = strstr(name, value);
548
549                   if (find)
550                      _msg_window_prop_client_append(array_of_ec, ec);
551                }
552           }
553      }
554
555    eldbus_message_iter_container_close(iter, array_of_ec);
556 }
557
558 static Eldbus_Message *
559 _e_info_server_cb_window_prop_get(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
560 {
561    Eldbus_Message *reply = eldbus_message_method_return_new(msg);
562    uint32_t mode = 0;
563    const char *value = NULL;
564
565    if (!eldbus_message_arguments_get(msg, "us", &mode, &value))
566      {
567         ERR("Error getting arguments.");
568         return reply;
569      }
570
571    _msg_window_prop_append(eldbus_message_iter_get(reply), mode, value);
572    return reply;
573 }
574
575 static Eldbus_Message *
576 _e_info_server_cb_topvwins_dump(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
577 {
578    Eldbus_Message *reply = eldbus_message_method_return_new(msg);
579    const char *dir;
580    Evas_Object *o;
581
582    if (!eldbus_message_arguments_get(msg, "s", &dir))
583      {
584         ERR("Error getting arguments.");
585         return reply;
586      }
587
588    for (o = evas_object_top_get(e_comp->evas); o; o = evas_object_below_get(o))
589      {
590         E_Client *ec = evas_object_data_get(o, "E_Client");
591         char fname[PATH_MAX];
592         Ecore_Window win;
593
594         if (!ec) continue;
595         if (e_client_util_ignored_get(ec)) continue;
596
597         win = e_client_util_win_get(ec);
598         snprintf(fname, sizeof(fname), "%s/0x%08x.png", dir, win);
599
600         e_info_server_dump_client(ec, fname);
601      }
602
603    return reply;
604 }
605
606 static Eldbus_Message *
607 _e_info_server_cb_eina_log_levels(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
608 {
609    Eldbus_Message *reply = eldbus_message_method_return_new(msg);
610    const char *start = NULL;
611
612    if (!eldbus_message_arguments_get(msg, "s", &start) || !start)
613      {
614         ERR("Error getting arguments.");
615         return reply;
616      }
617
618    while (1)
619      {
620         char module_name[256];
621         char *end = NULL;
622         char *tmp = NULL;
623         int level;
624
625         end = strchr(start, ':');
626         if (!end)
627            break;
628
629         // Parse level, keep going if failed
630         level = (int)strtol((char *)(end + 1), &tmp, 10);
631         if (tmp == (end + 1))
632            goto parse_end;
633
634         // Parse name
635         strncpy(module_name, start, MIN(end - start, (sizeof module_name) - 1));
636         module_name[end - start] = '\0';
637
638                   eina_log_domain_level_set((const char*)module_name, level);
639
640 parse_end:
641         start = strchr(tmp, ',');
642         if (start)
643            start++;
644         else
645            break;
646      }
647
648    return reply;
649 }
650
651 static Eldbus_Message *
652 _e_info_server_cb_eina_log_path(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
653 {
654    Eldbus_Message *reply = eldbus_message_method_return_new(msg);
655    const char *path = NULL;
656    static int old_stderr = -1;
657    int  log_fd = -1;
658    FILE *log_fl;
659
660    if (!eldbus_message_arguments_get(msg, "s", &path) || !path)
661      {
662         ERR("Error getting arguments.");
663         return reply;
664      }
665
666    if (old_stderr == -1)
667      old_stderr = dup(STDOUT_FILENO);
668
669    log_fl = fopen(path, "a");
670    if (!log_fl)
671      {
672         ERR("failed: open file(%s)\n", path);
673         return reply;
674      }
675
676    fflush(stderr);
677    close(STDOUT_FILENO);
678
679    setvbuf(log_fl, NULL, _IOLBF, 512);
680    log_fd = fileno(log_fl);
681
682    dup2(log_fd, STDOUT_FILENO);
683    fclose(log_fl);
684
685    return reply;
686 }
687
688 #ifdef HAVE_DLOG
689 static Eldbus_Message *
690 _e_info_server_cb_dlog_switch(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
691 {
692    Eldbus_Message *reply = eldbus_message_method_return_new(msg);
693    uint32_t onoff;
694
695    if (!eldbus_message_arguments_get(msg, "i", &onoff))
696      {
697         ERR("Error getting arguments.");
698         return reply;
699      }
700
701    if ((onoff == 1) || (onoff == 0))
702      e_log_dlog_enable(onoff);
703
704    return reply;
705 }
706 #endif
707
708 static Eldbus_Message *
709 _e_info_server_cb_rotation_query(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
710 {
711    Eldbus_Message *reply = eldbus_message_method_return_new(msg);
712
713    /* TODO: need implementation */
714
715    return reply;
716 }
717
718 static void
719 _e_info_event_rotation_free(void *data EINA_UNUSED, void *event)
720 {
721    E_Event_Info_Rotation_Message *ev = event;
722
723    e_object_unref(E_OBJECT(ev->zone));
724    free(ev);
725 }
726
727 static Eldbus_Message *
728 _e_info_server_cb_rotation_message(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
729 {
730    Eldbus_Message *reply = eldbus_message_method_return_new(msg);
731    E_Event_Info_Rotation_Message *ev;
732    E_Info_Rotation_Message rot_msg;
733    E_Zone *z;
734    Eina_List *l;
735    uint32_t zone_num;
736    uint32_t rval;
737
738    if (!eldbus_message_arguments_get(msg, "iii", &rot_msg, &zone_num, &rval))
739      {
740         ERR("Error getting arguments.");
741         return reply;
742      }
743
744    if (rot_msg == E_INFO_ROTATION_MESSAGE_SET)
745      {
746         /* check if rval is valid */
747         if ((rval > 270) || (rval % 90 != 0))
748           return reply;
749      }
750
751    ev = E_NEW(E_Event_Info_Rotation_Message, 1);
752    if (EINA_UNLIKELY(!ev))
753      {
754         ERR("Failed to allocate ""E_Event_Info_Rotation_Message""");
755         return reply;
756      }
757
758    if (zone_num == -1)
759      ev->zone = e_zone_current_get();
760    else
761      {
762         EINA_LIST_FOREACH(e_comp->zones, l, z)
763           {
764              if (z->num == zone_num)
765                ev->zone = z;
766           }
767      }
768
769    if (!ev->zone)
770      {
771         ERR("Failed to found zone by given num: num %d", zone_num);
772         free(ev);
773         return reply;
774      }
775
776    e_object_ref(E_OBJECT(ev->zone));
777    ev->message = rot_msg;
778    ev->rotation = rval;
779
780    ecore_event_add(E_EVENT_INFO_ROTATION_MESSAGE, ev, _e_info_event_rotation_free, NULL);
781
782    return reply;
783 }
784
785 /* wayland private function */
786 const char *
787 get_next_argument(const char *signature, struct argument_details *details)
788 {
789    details->nullable = 0;
790    for(; *signature; ++signature)
791      {
792         switch(*signature)
793           {
794            case 'i':
795            case 'u':
796            case 'f':
797            case 's':
798            case 'o':
799            case 'n':
800            case 'a':
801            case 'h':
802              details->type = *signature;
803              return signature + 1;
804            case '?':
805              details->nullable = 1;
806           }
807      }
808    details->type = '\0';
809    return signature;
810 }
811
812 static void
813 _e_info_server_protocol_debug_func(struct wl_closure *closure, struct wl_resource *resource, int send)
814 {
815    int i;
816    struct argument_details arg;
817    struct wl_object *target = &resource->object;
818    struct wl_client *wc = resource->client;
819    const char *signature = closure->message->signature;
820    struct timespec tp;
821    unsigned int time;
822    pid_t client_pid = -1;
823
824    if (wc) wl_client_get_credentials(wc, &client_pid, NULL, NULL);
825
826    clock_gettime(CLOCK_REALTIME, &tp);
827    time = (tp.tv_sec * 1000000L) + (tp.tv_nsec / 1000);
828
829    fprintf(stdout, "[%10.3f] %s%d%s%s@%u.%s(",
830               time / 1000.0,
831               send ? "Server -> Client [PID:" : "Server <- Client [PID:",
832               client_pid, "] ",
833               target->interface->name, target->id,
834               closure->message->name);
835
836    for (i = 0; i < closure->count; i++)
837      {
838         signature = get_next_argument(signature, &arg);
839         if (i > 0) fprintf(stdout, ", ");
840
841         switch (arg.type)
842           {
843            case 'u':
844              fprintf(stdout, "%u", closure->args[i].u);
845              break;
846            case 'i':
847              fprintf(stdout, "%d", closure->args[i].i);
848              break;
849            case 'f':
850              fprintf(stdout, "%f",
851              wl_fixed_to_double(closure->args[i].f));
852              break;
853            case 's':
854              fprintf(stdout, "\"%s\"", closure->args[i].s);
855              break;
856            case 'o':
857              if (closure->args[i].o)
858                fprintf(stdout, "%s@%u", closure->args[i].o->interface->name, closure->args[i].o->id);
859              else
860                fprintf(stdout, "nil");
861              break;
862            case 'n':
863              fprintf(stdout, "new id %s@", (closure->message->types[i]) ? closure->message->types[i]->name : "[unknown]");
864              if (closure->args[i].n != 0)
865                fprintf(stdout, "%u", closure->args[i].n);
866              else
867                fprintf(stdout, "nil");
868              break;
869            case 'a':
870              fprintf(stdout, "array");
871              break;
872            case 'h':
873              fprintf(stdout, "fd %d", closure->args[i].h);
874              break;
875           }
876      }
877
878    fprintf(stdout, ")\n");
879 }
880
881 static Eldbus_Message *
882 _e_info_server_cb_protocol_trace(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
883 {
884    Eldbus_Message *reply = eldbus_message_method_return_new(msg);
885    const char *path = NULL;
886    static int old_stderr = -1;
887    int  log_fd = -1;
888    FILE *log_fl;
889
890    if (!eldbus_message_arguments_get(msg, "s", &path) || !path)
891      {
892         ERR("Error getting arguments.");
893         return reply;
894      }
895
896    if (!strncmp(path, "disable", 7) && (old_stderr != -1))
897      {
898         dup2(old_stderr, STDOUT_FILENO);
899         close(old_stderr);
900         old_stderr = -1;
901         wl_debug_server_debug_func_set(NULL);
902         return reply;
903      }
904
905    if (old_stderr == -1)
906      old_stderr = dup(STDOUT_FILENO);
907
908    log_fl = fopen(path, "a");
909
910    if (!log_fl)
911      {
912         ERR("failed: open file(%s)\n", path);
913         return reply;
914      }
915
916    close(STDOUT_FILENO);
917
918    setvbuf(log_fl, NULL, _IOLBF, 512);
919    log_fd = fileno(log_fl);
920
921    dup2(log_fd, STDOUT_FILENO);
922    fclose(log_fl);
923
924    wl_debug_server_debug_func_set((wl_server_debug_func_ptr)_e_info_server_protocol_debug_func);
925
926    return reply;
927 }
928
929 static Eldbus_Message *
930 _e_info_server_cb_keymap_info_get(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
931 {
932    Eldbus_Message *reply = eldbus_message_method_return_new(msg);
933
934    eldbus_message_arguments_append(reply, "hi", e_comp_wl->xkb.fd, e_comp_wl->xkb.size);
935    return reply;
936 }
937
938 static Eldbus_Message *
939 _e_info_server_cb_fps_info_get(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
940 {
941    static double old_fps = 0;
942
943    Eldbus_Message *reply = eldbus_message_method_return_new(msg);
944    char buf[128] = {};
945
946    if (!e_comp->calc_fps)
947      {
948         e_comp->calc_fps = 1;
949      }
950
951    if (old_fps == e_comp->fps)
952      {
953         snprintf(buf, sizeof(buf), "no_update");
954      }
955    else if (e_comp->fps > 0.0)
956      {
957         if(e_comp->nocomp && e_comp->nocomp_ec)
958           snprintf(buf, sizeof(buf), "... FPS %3.1f(by 0x%x : %s)", e_comp->fps, e_client_util_win_get(e_comp->nocomp_ec), e_client_util_name_get(e_comp->nocomp_ec) ?: " ");
959         else
960           snprintf(buf, sizeof(buf), "... FPS %3.1f", e_comp->fps);
961         old_fps = e_comp->fps;
962      }
963    else
964      {
965         snprintf(buf, sizeof(buf), "... FPS N/A");
966      }
967
968    eldbus_message_arguments_append(reply, "s", buf);
969    return reply;
970 }
971
972 static Eldbus_Message *
973 e_info_server_cb_transform_message(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
974 {
975    Eldbus_Message *reply = eldbus_message_method_return_new(msg);
976    uint32_t enable, transform_id;
977    uint32_t x, y, sx, sy, degree;
978    uint32_t keep_ratio;
979    const char *value = NULL;
980    int32_t value_number;
981    Evas_Object *o;
982    E_Client *ec;
983
984    if (!eldbus_message_arguments_get(msg, "siiiiiiii", &value, &transform_id, &enable, &x, &y, &sx, &sy, &degree, &keep_ratio))
985      {
986         ERR("Error getting arguments.");
987         return reply;
988      }
989
990    if (strlen(value) >= 2 && value[0] == '0' && value[1] == 'x')
991       sscanf(value, "%x", &value_number);
992    else
993       sscanf(value, "%d", &value_number);
994
995    for (o = evas_object_top_get(e_comp->evas); o; o = evas_object_below_get(o))
996      {
997         ec = evas_object_data_get(o, "E_Client");
998         Ecore_Window win;
999         E_Info_Transform *transform_info;
1000
1001         if (!ec) continue;
1002
1003         win = e_client_util_win_get(ec);
1004
1005         if (win != value_number) continue;
1006         transform_info = _e_info_transform_find(ec, transform_id);
1007
1008         if (transform_info)
1009           {
1010              _e_info_transform_set(transform_info, enable, x, y, sx, sy, degree, keep_ratio);
1011
1012              if (!enable)
1013                 _e_info_transform_del_with_id(ec, transform_id);
1014           }
1015         else
1016           {
1017              if (enable)
1018                {
1019                   _e_info_transform_new(ec, transform_id, enable, x, y, sx, sy, degree, keep_ratio);
1020                }
1021           }
1022
1023         break;
1024      }
1025
1026    return reply;
1027 }
1028
1029 static Eina_Bool
1030 _e_info_server_cb_buffer_change(void *data, int type, void *event)
1031 {
1032    E_Client *ec;
1033    E_Event_Client *ev = event;
1034    Ecore_Window event_win;
1035    char fname[PATH_MAX];
1036    int count;
1037
1038    EINA_SAFETY_ON_NULL_RETURN_VAL(ev, ECORE_CALLBACK_PASS_ON);
1039    EINA_SAFETY_ON_NULL_RETURN_VAL(ev->ec, ECORE_CALLBACK_PASS_ON);
1040
1041    /* dump buffer change call event buffer */
1042    ec = ev->ec;
1043    if (e_object_is_del(E_OBJECT(ec)))
1044      {
1045         ERR("%s: e_object_is_del(E_OBJECT(ec) return\n", __func__);
1046         return ECORE_CALLBACK_PASS_ON;
1047      }
1048    if (e_client_util_ignored_get(ec))
1049      {
1050         ERR("%s: e_client_util_ignored_get(ec) true. return\n", __func__);
1051         return ECORE_CALLBACK_PASS_ON;
1052      }
1053    event_win = e_client_util_win_get(ec);
1054
1055    if (e_info_dump_count == 1000)
1056      e_info_dump_count = 1;
1057    count = e_info_dump_count++;
1058    snprintf(fname, sizeof(fname), "%s/%03d_0x%08x.png", e_info_dump_path, count, event_win);
1059    e_info_server_dump_client(ec, fname);
1060
1061 #if 0
1062    /* dump all buffers */
1063    char path[PATH_MAX];
1064
1065    snprintf(path, sizeof(path), "%s/%d", e_info_dump_path, count);
1066    if ((mkdir(path, 0755)) < 0)
1067      {
1068         printf("%s: mkdir '%s' fail\n", __func__, path);
1069         return ECORE_CALLBACK_PASS_ON;
1070      }
1071
1072    for (o = evas_object_top_get(e_comp->evas); o; o = evas_object_below_get(o))
1073      {
1074         E_Client *ec = evas_object_data_get(o, "E_Client");
1075         Ecore_Window win;
1076
1077         if (!ec) continue;
1078         if (e_client_util_ignored_get(ec)) continue;
1079
1080         win = e_client_util_win_get(ec);
1081
1082         snprintf(fname, sizeof(fname), "%s/0x%08x.png", path, win);
1083
1084         e_info_server_dump_client(ec, fname);
1085      }
1086 #endif
1087    DBG("%d, %s dump excute\n", count, fname);
1088
1089    return ECORE_CALLBACK_PASS_ON;
1090 }
1091
1092 static char *
1093 _e_info_server_dump_directory_make(void)
1094 {
1095    char *fullpath;
1096    time_t timer;
1097    struct tm *t, *buf;
1098
1099    timer = time(NULL);
1100
1101    buf = calloc (1, sizeof (struct tm));
1102    EINA_SAFETY_ON_NULL_RETURN_VAL(buf, NULL);
1103    t = localtime_r(&timer, buf);
1104    if (!t)
1105      {
1106         free(buf);
1107         ERR("fail to get local time\n");
1108         return NULL;
1109      }
1110
1111    fullpath = (char *)calloc(1, PATH_MAX * sizeof(char));
1112    if (!fullpath)
1113      {
1114         free(buf);
1115         ERR("fail to alloc pathname memory\n");
1116         return NULL;
1117      }
1118
1119    snprintf(fullpath, PATH_MAX, "/tmp/dump_%04d%02d%02d.%02d%02d%02d",
1120             t->tm_year+1900, t->tm_mon+1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec);
1121
1122    free(buf);
1123
1124    if ((mkdir(fullpath, 0755)) < 0)
1125      {
1126         ERR("%s: mkdir '%s' fail\n", __func__, fullpath);
1127         free(fullpath);
1128         return NULL;
1129      }
1130
1131    return fullpath;
1132 }
1133
1134 static Eldbus_Message *
1135 _e_info_server_cb_buffer_dump(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
1136 {
1137    Eldbus_Message *reply = eldbus_message_method_return_new(msg);
1138    int start = 0;
1139
1140    if (!eldbus_message_arguments_get(msg, "i", &start))
1141      {
1142         ERR("Error getting arguments.");
1143         return reply;
1144      }
1145
1146    if (start == 1)
1147      {
1148         if (e_info_dump_running == 1)
1149           return reply;
1150         e_info_dump_running = 1;
1151         e_info_dump_count = 1;
1152         e_info_dump_path = _e_info_server_dump_directory_make();
1153         if (e_info_dump_path == NULL)
1154           {
1155              e_info_dump_running = 0;
1156              e_info_dump_count = 0;
1157              ERR("dump_buffers start fail\n");
1158           }
1159         else
1160           {
1161              tdm_helper_dump_start(e_info_dump_path, &e_info_dump_count);
1162              E_LIST_HANDLER_APPEND(e_info_dump_hdlrs, E_EVENT_CLIENT_BUFFER_CHANGE,
1163                                _e_info_server_cb_buffer_change, NULL);
1164           }
1165      }
1166    else
1167      {
1168         if (e_info_dump_running == 0)
1169           return reply;
1170         tdm_helper_dump_stop();
1171         E_FREE_LIST(e_info_dump_hdlrs, ecore_event_handler_del);
1172         e_info_dump_hdlrs = NULL;
1173         if (e_info_dump_path)
1174           {
1175              free(e_info_dump_path);
1176              e_info_dump_path = NULL;
1177           }
1178         e_info_dump_count = 0;
1179         e_info_dump_running = 0;
1180      }
1181
1182    return reply;
1183 }
1184
1185 #ifdef HAVE_HWC
1186 static Eldbus_Message *
1187 e_info_server_cb_hwc_trace_message(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
1188 {
1189    Eldbus_Message *reply = eldbus_message_method_return_new(msg);
1190    uint32_t onoff;
1191
1192    if (!eldbus_message_arguments_get(msg, "i", &onoff))
1193      {
1194         ERR("Error getting arguments.");
1195         return reply;
1196      }
1197
1198    if (onoff == 1 || onoff == 0)
1199      e_comp_hwc_trace_debug(onoff);
1200
1201    return reply;
1202 }
1203 #endif
1204
1205 static const Eldbus_Method methods[] = {
1206    { "get_window_info", NULL, ELDBUS_ARGS({"a("VALUE_TYPE_FOR_TOPVWINS")", "array of ec"}), _e_info_server_cb_window_info_get, 0 },
1207    { "dump_topvwins", ELDBUS_ARGS({"s", "directory"}), NULL, _e_info_server_cb_topvwins_dump, 0 },
1208    { "eina_log_levels", ELDBUS_ARGS({"s", "eina log levels"}), NULL, _e_info_server_cb_eina_log_levels, 0 },
1209    { "eina_log_path", ELDBUS_ARGS({"s", "eina log path"}), NULL, _e_info_server_cb_eina_log_path, 0 },
1210 #ifdef HAVE_DLOG
1211    { "dlog", ELDBUS_ARGS({"i", "using dlog"}), NULL, _e_info_server_cb_dlog_switch, 0},
1212 #endif
1213    { "get_window_prop", ELDBUS_ARGS({"us", "query_mode_value"}), ELDBUS_ARGS({"a(ss)", "array_of_ec"}), _e_info_server_cb_window_prop_get, 0},
1214    { "get_connected_clients", NULL, ELDBUS_ARGS({"a(ss)", "array of ec"}), _e_info_server_cb_connected_clients_get, 0 },
1215    { "rotation_query", ELDBUS_ARGS({"i", "query_rotation"}), NULL, _e_info_server_cb_rotation_query, 0},
1216    { "rotation_message", ELDBUS_ARGS({"iii", "rotation_message"}), NULL, _e_info_server_cb_rotation_message, 0},
1217    { "get_res_lists", ELDBUS_ARGS({VALUE_TYPE_REQUEST_RESLIST, "client resource"}), ELDBUS_ARGS({"a("VALUE_TYPE_REPLY_RESLIST")", "array of client resources"}), _e_info_server_cb_res_lists_get, 0 },
1218    { "get_input_devices", NULL, ELDBUS_ARGS({"a("VALUE_TYPE_FOR_INPUTDEV")", "array of input"}), _e_info_server_cb_input_device_info_get, 0},
1219    { "protocol_trace", ELDBUS_ARGS({"s", "protocol_trace"}), NULL, _e_info_server_cb_protocol_trace, 0},
1220    { "get_fps_info", NULL, ELDBUS_ARGS({"s", "fps request"}), _e_info_server_cb_fps_info_get, 0},
1221    { "transform_message", ELDBUS_ARGS({"siiiiiiii", "transform_message"}), NULL, e_info_server_cb_transform_message, 0},
1222    { "dump_buffers", ELDBUS_ARGS({"i", "start"}), NULL, _e_info_server_cb_buffer_dump, 0 },
1223 #ifdef HAVE_HWC
1224    { "hwc_trace_message", ELDBUS_ARGS({"i", "hwc_trace_message"}), NULL, e_info_server_cb_hwc_trace_message, 0},
1225 #endif
1226    { "get_keymap", NULL, ELDBUS_ARGS({"hi", "keymap fd"}), _e_info_server_cb_keymap_info_get, 0},
1227    { NULL, NULL, NULL, NULL, 0 }
1228 };
1229
1230 static const Eldbus_Service_Interface_Desc iface_desc = {
1231      IFACE, methods, NULL, NULL, NULL, NULL
1232 };
1233
1234 EINTERN int
1235 e_info_server_init(void)
1236 {
1237    eldbus_init();
1238
1239    e_info_server.conn = eldbus_connection_get(ELDBUS_CONNECTION_TYPE_SYSTEM);
1240    EINA_SAFETY_ON_NULL_GOTO(e_info_server.conn, err);
1241
1242    e_info_server.iface = eldbus_service_interface_register(e_info_server.conn,
1243                                                            PATH,
1244                                                            &iface_desc);
1245    EINA_SAFETY_ON_NULL_GOTO(e_info_server.iface, err);
1246
1247    E_EVENT_INFO_ROTATION_MESSAGE = ecore_event_type_new();
1248
1249    return 1;
1250
1251 err:
1252    e_info_server_shutdown();
1253    return 0;
1254 }
1255
1256 EINTERN int
1257 e_info_server_shutdown(void)
1258 {
1259    if (e_info_server.iface)
1260      {
1261         eldbus_service_interface_unregister(e_info_server.iface);
1262         e_info_server.iface = NULL;
1263      }
1264
1265    if (e_info_server.conn)
1266      {
1267         eldbus_connection_unref(e_info_server.conn);
1268         e_info_server.conn = NULL;
1269      }
1270
1271    if (e_info_transform_list)
1272      {
1273         E_Info_Transform *info;
1274         Eina_List *l, *l_next;
1275
1276         EINA_LIST_FOREACH_SAFE(e_info_transform_list, l, l_next, info)
1277           {
1278              _e_info_transform_del(info);
1279           }
1280
1281         eina_list_free(e_info_transform_list);
1282         e_info_transform_list = NULL;
1283      }
1284
1285    if (e_info_dump_running == 1)
1286      tdm_helper_dump_stop();
1287    if (e_info_dump_hdlrs)
1288      {
1289         E_FREE_LIST(e_info_dump_hdlrs, ecore_event_handler_del);
1290         e_info_dump_hdlrs = NULL;
1291      }
1292    if (e_info_dump_path)
1293      {
1294         free(e_info_dump_path);
1295         e_info_dump_path = NULL;
1296      }
1297    e_info_dump_count = 0;
1298    e_info_dump_running = 0;
1299
1300    eldbus_shutdown();
1301
1302    return 1;
1303 }
1304
1305 EINTERN void
1306 e_info_server_dump_client(E_Client *ec, char *fname)
1307 {
1308    void *data = NULL;
1309    int w = 0, h = 0;
1310    Ecore_Evas *ee = NULL;
1311    Evas_Object *img = NULL;
1312
1313    if (!ec) return;
1314    if (e_client_util_ignored_get(ec)) return;
1315
1316  #ifdef HAVE_WAYLAND_ONLY
1317    struct wl_shm_buffer *shmbuffer = NULL;
1318    E_Comp_Wl_Buffer *buffer = e_pixmap_resource_get(ec->pixmap);
1319    if (!buffer) return;
1320
1321    if (buffer->type == E_COMP_WL_BUFFER_TYPE_SHM)
1322      {
1323         shmbuffer = wl_shm_buffer_get(buffer->resource);
1324         if (shmbuffer)
1325           {
1326              data = wl_shm_buffer_get_data(shmbuffer);
1327              w = wl_shm_buffer_get_stride(shmbuffer)/4;
1328              h = wl_shm_buffer_get_height(shmbuffer);
1329           }
1330      }
1331    else if (buffer->type == E_COMP_WL_BUFFER_TYPE_NATIVE)
1332      {
1333         tbm_surface_info_s surface_info;
1334         tbm_surface_h tbm_surface = wayland_tbm_server_get_surface(NULL, buffer->resource);
1335
1336         memset(&surface_info, 0, sizeof(tbm_surface_info_s));
1337         tbm_surface_map(tbm_surface, TBM_SURF_OPTION_READ, &surface_info);
1338
1339         data = surface_info.planes[0].ptr;
1340         w = surface_info.planes[0].stride/4;
1341         h = surface_info.height;
1342      }
1343    else
1344      {
1345         ERR("Invalid resource:%u", wl_resource_get_id(buffer->resource));
1346      }
1347  #endif
1348
1349    EINA_SAFETY_ON_NULL_GOTO(data, err);
1350
1351    ee = ecore_evas_buffer_new(1, 1);
1352    EINA_SAFETY_ON_NULL_GOTO(ee, err);
1353
1354    img = evas_object_image_add(ecore_evas_get(ee));
1355    EINA_SAFETY_ON_NULL_GOTO(img, err);
1356
1357    evas_object_image_alpha_set(img, EINA_TRUE);
1358    evas_object_image_size_set(img, w, h);
1359    evas_object_image_data_set(img, data);
1360
1361    if (!evas_object_image_save(img, fname, NULL, "compress=1 quality=100"))
1362      ERR("Cannot save window to '%s'", fname);
1363
1364  err:
1365  #ifdef HAVE_WAYLAND_ONLY
1366    if (data && buffer->type == E_COMP_WL_BUFFER_TYPE_NATIVE)
1367      {
1368         tbm_surface_h tbm_surface = wayland_tbm_server_get_surface(NULL, buffer->resource);
1369         tbm_surface_unmap(tbm_surface);
1370      }
1371  #endif
1372
1373    if (img) evas_object_del(img);
1374    if (ee) ecore_evas_free(ee);
1375 }
1376
1377
1378 static E_Info_Transform*
1379 _e_info_transform_new(E_Client *ec, int id, int enable, int x, int y, int sx, int sy, int degree, int keep_ratio)
1380 {
1381    E_Info_Transform *result = NULL;
1382    result = _e_info_transform_find(ec, id);
1383
1384    if (!result)
1385      {
1386         result = (E_Info_Transform*)malloc(sizeof(E_Info_Transform));
1387         memset(result, 0, sizeof(E_Info_Transform));
1388         result->id = id;
1389         result->ec = ec;
1390         result->transform = e_util_transform_new();
1391         _e_info_transform_set(result, enable, x, y, sx, sy, degree, keep_ratio);
1392         e_info_transform_list = eina_list_append(e_info_transform_list, result);
1393
1394      }
1395
1396    return result;
1397 }
1398
1399 static E_Info_Transform*
1400 _e_info_transform_find(E_Client *ec, int id)
1401 {
1402    Eina_List *l;
1403    E_Info_Transform *transform;
1404    E_Info_Transform *result = NULL;
1405
1406    EINA_LIST_FOREACH(e_info_transform_list, l, transform)
1407      {
1408         if (transform->ec == ec && transform->id == id)
1409           {
1410              result =  transform;
1411              break;
1412           }
1413      }
1414
1415    return result;
1416 }
1417
1418 static void
1419 _e_info_transform_set(E_Info_Transform *transform, int enable, int x, int y, int sx, int sy, int degree, int keep_ratio)
1420 {
1421    if (!transform) return;
1422    if (!transform->transform) return;
1423
1424    e_util_transform_move(transform->transform, (double)x, (double)y, 0.0);
1425    e_util_transform_scale(transform->transform, (double)sx / 100.0, (double)sy / 100.0, 1.0);
1426    e_util_transform_rotation(transform->transform, 0.0, 0.0, degree);
1427    e_util_transform_keep_ratio_set(transform->transform, keep_ratio);
1428
1429    if (enable)
1430       e_client_transform_core_add(transform->ec, transform->transform);
1431    else
1432       e_client_transform_core_remove(transform->ec, transform->transform);
1433
1434    e_client_transform_core_update(transform->ec);
1435 }
1436
1437 static void
1438 _e_info_transform_del(E_Info_Transform *transform)
1439 {
1440    if (!transform) return;
1441
1442    e_info_transform_list = eina_list_remove(e_info_transform_list, transform);
1443    e_client_transform_core_remove(transform->ec, transform->transform);
1444    e_util_transform_del(transform->transform);
1445    free(transform);
1446 }
1447
1448 static void
1449 _e_info_transform_del_with_id(E_Client *ec, int id)
1450 {
1451    E_Info_Transform *transform = NULL;
1452    if (!ec) return;
1453
1454    transform = _e_info_transform_find(ec, id);
1455
1456    if (transform)
1457       _e_info_transform_del(transform);
1458 }