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>
10 void wl_map_for_each(struct wl_map *map, void *func, void *data);
13 #include "e_comp_hwc.h"
16 #define BUS "org.enlightenment.wm"
17 #define PATH "/org/enlightenment/wm"
18 #define IFACE "org.enlightenment.wm.info"
20 E_API int E_EVENT_INFO_ROTATION_MESSAGE = -1;
22 typedef struct _E_Info_Server
24 Eldbus_Connection *conn;
25 Eldbus_Service_Interface *iface;
28 typedef struct _E_Info_Transform
31 E_Util_Transform *transform;
36 static E_Info_Server e_info_server;
37 static Eina_List *e_info_transform_list = NULL;
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;
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"
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);
56 _msg_clients_append(Eldbus_Message_Iter *iter)
58 Eldbus_Message_Iter *array_of_ec;
62 eldbus_message_iter_arguments_append(iter, "a("VALUE_TYPE_FOR_TOPVWINS")", &array_of_ec);
65 for (o = evas_object_top_get(e_comp->evas); o; o = evas_object_below_get(o))
67 Eldbus_Message_Iter* struct_of_ec;
74 ec = evas_object_data_get(o, "E_Client");
76 if (e_client_util_ignored_get(ec)) continue;
78 win = e_client_util_win_get(ec);
79 e_comp_layer_name_get(ec->layer, layer_name, sizeof(layer_name));
82 res_id = e_pixmap_res_id_get(ec->pixmap);
85 #ifdef HAVE_WAYLAND_ONLY
90 E_Comp_Wl_Client_Data *cdata = (E_Comp_Wl_Client_Data*)ec->comp_data;
92 wl_client_get_credentials(wl_resource_get_client(cdata->surface), &pid, NULL, NULL);
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
107 eldbus_message_iter_arguments_append(array_of_ec, "("VALUE_TYPE_FOR_TOPVWINS")", &struct_of_ec);
109 eldbus_message_iter_arguments_append
110 (struct_of_ec, VALUE_TYPE_FOR_TOPVWINS,
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);
118 eldbus_message_iter_container_close(array_of_ec, struct_of_ec);
121 eldbus_message_iter_container_close(iter, array_of_ec);
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)
128 Eldbus_Message *reply = eldbus_message_method_return_new(msg);
130 _msg_clients_append(eldbus_message_iter_get(reply));
136 _input_msg_clients_append(Eldbus_Message_Iter *iter)
138 Eldbus_Message_Iter *array_of_input;
140 E_Comp_Wl_Data *cdata;
141 E_Comp_Wl_Input_Device *dev;
143 eldbus_message_iter_arguments_append(iter, "a("VALUE_TYPE_FOR_INPUTDEV")", &array_of_input);
145 cdata = e_comp->wl_comp_data;
146 EINA_LIST_FOREACH(cdata->input_device_manager.device_list, l, dev)
148 Eldbus_Message_Iter *struct_of_input;
150 eldbus_message_iter_arguments_append(array_of_input, "("VALUE_TYPE_FOR_INPUTDEV")", &struct_of_input);
152 eldbus_message_iter_arguments_append
153 (struct_of_input, VALUE_TYPE_FOR_INPUTDEV,
154 dev->name, dev->identifier, dev->capability);
156 eldbus_message_iter_container_close(array_of_input, struct_of_input);
158 eldbus_message_iter_container_close(iter, array_of_input);
162 static Eldbus_Message *
163 _e_info_server_cb_input_device_info_get(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
165 Eldbus_Message *reply = eldbus_message_method_return_new(msg);
167 _input_msg_clients_append(eldbus_message_iter_get(reply));
173 _msg_connected_clients_append(Eldbus_Message_Iter *iter)
175 Eldbus_Message_Iter *array_of_ec;
179 eldbus_message_iter_arguments_append(iter, "a(ss)", &array_of_ec);
182 E_Comp_Connected_Client_Info *cinfo;
185 Eldbus_Message_Iter* struct_of_ec;
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);})
194 EINA_LIST_FOREACH(e_comp->connected_clients, l, cinfo)
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))
203 ec = evas_object_data_get(o, "E_Client");
205 if (e_client_util_ignored_get(ec)) continue;
207 win = e_client_util_win_get(ec);
210 res_id = e_pixmap_res_id_get(ec->pixmap);
211 #ifdef HAVE_WAYLAND_ONLY
214 E_Comp_Wl_Client_Data *cdata = (E_Comp_Wl_Client_Data*)ec->comp_data;
216 wl_client_get_credentials(wl_resource_get_client(cdata->surface), &pid, NULL, NULL);
219 if (cinfo->pid == pid)
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);
227 eldbus_message_iter_container_close(iter, array_of_ec);
230 static Eldbus_Message *
231 _e_info_server_cb_connected_clients_get(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
233 Eldbus_Message *reply = eldbus_message_method_return_new(msg);
235 _msg_connected_clients_append(eldbus_message_iter_get(reply));
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))
245 static int resurceCnt = 0;
248 _e_info_server_get_resource(void *element, void *data)
250 struct wl_resource *resource = element;
251 Eldbus_Message_Iter* array_of_res= data;
252 Eldbus_Message_Iter* struct_of_res;
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);
261 _msg_clients_res_list_append(Eldbus_Message_Iter *iter, uint32_t mode, int id)
263 Eldbus_Message_Iter *array_of_res;
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;
277 eldbus_message_iter_arguments_append(iter, "a("VALUE_TYPE_REPLY_RESLIST")", &array_of_res);
280 if (!(cdata = e_comp->wl_comp_data)) return;
281 if (!cdata->wl.disp) return;
283 client_list = wl_display_get_client_list(cdata->wl.disp);
285 wl_client_for_each(client, client_list)
287 Eldbus_Message_Iter* struct_of_res;
289 wl_client_get_credentials(client, &pid, NULL, NULL);
291 if ((type == PID) && (pid != id)) continue;
293 eldbus_message_iter_arguments_append(array_of_res, "("VALUE_TYPE_REPLY_RESLIST")", &struct_of_res);
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);
299 res_objs = wl_client_get_resources(client);
300 wl_map_for_each(res_objs, _e_info_server_get_resource, array_of_res);
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);
306 eldbus_message_iter_container_close(iter, array_of_res);
309 static Eldbus_Message *
310 _e_info_server_cb_res_lists_get(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
312 Eldbus_Message *reply = eldbus_message_method_return_new(msg);
316 if (!eldbus_message_arguments_get(msg, VALUE_TYPE_REQUEST_RESLIST, &mode, &pid))
318 ERR("Error getting arguments.");
322 _msg_clients_res_list_append(eldbus_message_iter_get(reply), mode, pid);
328 _msg_window_prop_client_append(Eldbus_Message_Iter *iter, E_Client *target_ec)
330 Eldbus_Message_Iter* struct_of_ec;
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,};
341 if (!target_ec) return;
343 if (target_ec->pixmap)
344 snprintf(win_resid, sizeof(win_resid), "%d", e_pixmap_res_id_get(target_ec->pixmap));
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);
349 if (target_ec->transients)
354 EINA_LIST_FOREACH(target_ec->transients, l, child)
357 snprintf(temp, sizeof(temp), "0x%x", e_client_util_win_get(child));
358 strncat(transients, temp, sizeof(transients) - strlen(transients));
362 if (target_ec->shape_rects && target_ec->shape_rects_num > 0)
365 for (i = 0 ; i < target_ec->shape_rects_num ; ++i)
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));
374 if (target_ec->shape_input_rects && target_ec->shape_input_rects_num > 0)
377 for (i = 0 ; i < target_ec->shape_input_rects_num ; ++i)
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));
386 #ifdef HAVE_WAYLAND_ONLY
387 if (target_ec->comp_data)
390 E_Comp_Wl_Client_Data *cdata = (E_Comp_Wl_Client_Data*)target_ec->comp_data;
393 wl_client_get_credentials(wl_resource_get_client(cdata->surface), &pid, NULL, NULL);
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);})
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);})
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)
454 int count = e_client_transform_core_transform_count_get(target_ec);
456 __WINDOW_PROP_ARG_APPEND(" ", "[id] [move] [scale] [rotation] [keep_ratio]");
457 for (i = 0 ; i < count ; ++i)
459 double dx, dy, dsx, dsy, drz;
463 E_Util_Transform *transform = e_client_transform_core_transform_get(target_ec, i);
464 if (!transform) continue;
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);
473 rz = (int)(drz + 0.5);
475 __WINDOW_PROP_ARG_APPEND_TYPE("Transform", "[%d] [%d, %d] [%2.1f, %2.1f] [%d] [%d]", i, x, y, dsx, dsy, rz, keep_ratio);
478 #undef __WINDOW_PROP_ARG_APPEND
479 #undef __WINDOW_PROP_ARG_APPEND_TYPE
483 _msg_window_prop_append(Eldbus_Message_Iter *iter, uint32_t mode, const char *value)
485 const static int WINDOW_ID_MODE = 0;
486 const static int WINDOW_PID_MODE = 1;
487 const static int WINDOW_NAME_MODE = 2;
489 Eldbus_Message_Iter *array_of_ec;
492 int32_t value_number = 0;
494 eldbus_message_iter_arguments_append(iter, "a(ss)", &array_of_ec);
496 if (mode == WINDOW_ID_MODE || mode == WINDOW_PID_MODE)
498 if (!value) value_number = 0;
501 if (strlen(value) >= 2 && value[0] == '0' && value[1] == 'x')
502 sscanf(value, "%x", &value_number);
504 sscanf(value, "%d", &value_number);
508 for (o = evas_object_top_get(e_comp->evas); o; o = evas_object_below_get(o))
510 ec = evas_object_data_get(o, "E_Client");
513 if (mode == WINDOW_ID_MODE)
515 Ecore_Window win = e_client_util_win_get(ec);
517 if (win == value_number)
519 _msg_window_prop_client_append(array_of_ec, ec);
523 else if (mode == WINDOW_PID_MODE)
526 #ifdef HAVE_WAYLAND_ONLY
529 E_Comp_Wl_Client_Data *cdata = (E_Comp_Wl_Client_Data*)ec->comp_data;
532 wl_client_get_credentials(wl_resource_get_client(cdata->surface), &pid, NULL, NULL);
536 if (pid == value_number)
538 _msg_window_prop_client_append(array_of_ec, ec);
541 else if (mode == WINDOW_NAME_MODE)
543 const char *name = e_client_util_name_get(ec) ?: "NO NAME";
545 if (name != NULL && value != NULL)
547 const char *find = strstr(name, value);
550 _msg_window_prop_client_append(array_of_ec, ec);
555 eldbus_message_iter_container_close(iter, array_of_ec);
558 static Eldbus_Message *
559 _e_info_server_cb_window_prop_get(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
561 Eldbus_Message *reply = eldbus_message_method_return_new(msg);
563 const char *value = NULL;
565 if (!eldbus_message_arguments_get(msg, "us", &mode, &value))
567 ERR("Error getting arguments.");
571 _msg_window_prop_append(eldbus_message_iter_get(reply), mode, value);
575 static Eldbus_Message *
576 _e_info_server_cb_topvwins_dump(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
578 Eldbus_Message *reply = eldbus_message_method_return_new(msg);
582 if (!eldbus_message_arguments_get(msg, "s", &dir))
584 ERR("Error getting arguments.");
588 for (o = evas_object_top_get(e_comp->evas); o; o = evas_object_below_get(o))
590 E_Client *ec = evas_object_data_get(o, "E_Client");
591 char fname[PATH_MAX];
595 if (e_client_util_ignored_get(ec)) continue;
597 win = e_client_util_win_get(ec);
598 snprintf(fname, sizeof(fname), "%s/0x%08x.png", dir, win);
600 e_info_server_dump_client(ec, fname);
606 static Eldbus_Message *
607 _e_info_server_cb_eina_log_levels(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
609 Eldbus_Message *reply = eldbus_message_method_return_new(msg);
610 const char *start = NULL;
612 if (!eldbus_message_arguments_get(msg, "s", &start) || !start)
614 ERR("Error getting arguments.");
620 char module_name[256];
625 end = strchr(start, ':');
629 // Parse level, keep going if failed
630 level = (int)strtol((char *)(end + 1), &tmp, 10);
631 if (tmp == (end + 1))
635 strncpy(module_name, start, MIN(end - start, (sizeof module_name) - 1));
636 module_name[end - start] = '\0';
638 eina_log_domain_level_set((const char*)module_name, level);
641 start = strchr(tmp, ',');
651 static Eldbus_Message *
652 _e_info_server_cb_eina_log_path(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
654 Eldbus_Message *reply = eldbus_message_method_return_new(msg);
655 const char *path = NULL;
656 static int old_stderr = -1;
660 if (!eldbus_message_arguments_get(msg, "s", &path) || !path)
662 ERR("Error getting arguments.");
666 if (old_stderr == -1)
667 old_stderr = dup(STDOUT_FILENO);
669 log_fl = fopen(path, "a");
672 ERR("failed: open file(%s)\n", path);
677 close(STDOUT_FILENO);
679 setvbuf(log_fl, NULL, _IOLBF, 512);
680 log_fd = fileno(log_fl);
682 dup2(log_fd, STDOUT_FILENO);
689 static Eldbus_Message *
690 _e_info_server_cb_dlog_switch(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
692 Eldbus_Message *reply = eldbus_message_method_return_new(msg);
695 if (!eldbus_message_arguments_get(msg, "i", &onoff))
697 ERR("Error getting arguments.");
701 if ((onoff == 1) || (onoff == 0))
702 e_log_dlog_enable(onoff);
708 static Eldbus_Message *
709 _e_info_server_cb_rotation_query(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
711 Eldbus_Message *reply = eldbus_message_method_return_new(msg);
713 /* TODO: need implementation */
719 _e_info_event_rotation_free(void *data EINA_UNUSED, void *event)
721 E_Event_Info_Rotation_Message *ev = event;
723 e_object_unref(E_OBJECT(ev->zone));
727 static Eldbus_Message *
728 _e_info_server_cb_rotation_message(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
730 Eldbus_Message *reply = eldbus_message_method_return_new(msg);
731 E_Event_Info_Rotation_Message *ev;
732 E_Info_Rotation_Message rot_msg;
738 if (!eldbus_message_arguments_get(msg, "iii", &rot_msg, &zone_num, &rval))
740 ERR("Error getting arguments.");
744 if (rot_msg == E_INFO_ROTATION_MESSAGE_SET)
746 /* check if rval is valid */
747 if ((rval > 270) || (rval % 90 != 0))
751 ev = E_NEW(E_Event_Info_Rotation_Message, 1);
752 if (EINA_UNLIKELY(!ev))
754 ERR("Failed to allocate ""E_Event_Info_Rotation_Message""");
759 ev->zone = e_zone_current_get();
762 EINA_LIST_FOREACH(e_comp->zones, l, z)
764 if (z->num == zone_num)
771 ERR("Failed to found zone by given num: num %d", zone_num);
776 e_object_ref(E_OBJECT(ev->zone));
777 ev->message = rot_msg;
780 ecore_event_add(E_EVENT_INFO_ROTATION_MESSAGE, ev, _e_info_event_rotation_free, NULL);
785 /* wayland private function */
787 get_next_argument(const char *signature, struct argument_details *details)
789 details->nullable = 0;
790 for(; *signature; ++signature)
802 details->type = *signature;
803 return signature + 1;
805 details->nullable = 1;
808 details->type = '\0';
813 _e_info_server_protocol_debug_func(struct wl_closure *closure, struct wl_resource *resource, int send)
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;
822 pid_t client_pid = -1;
824 if (wc) wl_client_get_credentials(wc, &client_pid, NULL, NULL);
826 clock_gettime(CLOCK_REALTIME, &tp);
827 time = (tp.tv_sec * 1000000L) + (tp.tv_nsec / 1000);
829 fprintf(stdout, "[%10.3f] %s%d%s%s@%u.%s(",
831 send ? "Server -> Client [PID:" : "Server <- Client [PID:",
833 target->interface->name, target->id,
834 closure->message->name);
836 for (i = 0; i < closure->count; i++)
838 signature = get_next_argument(signature, &arg);
839 if (i > 0) fprintf(stdout, ", ");
844 fprintf(stdout, "%u", closure->args[i].u);
847 fprintf(stdout, "%d", closure->args[i].i);
850 fprintf(stdout, "%f",
851 wl_fixed_to_double(closure->args[i].f));
854 fprintf(stdout, "\"%s\"", closure->args[i].s);
857 if (closure->args[i].o)
858 fprintf(stdout, "%s@%u", closure->args[i].o->interface->name, closure->args[i].o->id);
860 fprintf(stdout, "nil");
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);
867 fprintf(stdout, "nil");
870 fprintf(stdout, "array");
873 fprintf(stdout, "fd %d", closure->args[i].h);
878 fprintf(stdout, ")\n");
881 static Eldbus_Message *
882 _e_info_server_cb_protocol_trace(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
884 Eldbus_Message *reply = eldbus_message_method_return_new(msg);
885 const char *path = NULL;
886 static int old_stderr = -1;
890 if (!eldbus_message_arguments_get(msg, "s", &path) || !path)
892 ERR("Error getting arguments.");
896 if (!strncmp(path, "disable", 7) && (old_stderr != -1))
898 dup2(old_stderr, STDOUT_FILENO);
901 wl_debug_server_debug_func_set(NULL);
905 if (old_stderr == -1)
906 old_stderr = dup(STDOUT_FILENO);
908 log_fl = fopen(path, "a");
912 ERR("failed: open file(%s)\n", path);
916 close(STDOUT_FILENO);
918 setvbuf(log_fl, NULL, _IOLBF, 512);
919 log_fd = fileno(log_fl);
921 dup2(log_fd, STDOUT_FILENO);
924 wl_debug_server_debug_func_set((wl_server_debug_func_ptr)_e_info_server_protocol_debug_func);
929 static Eldbus_Message *
930 _e_info_server_cb_keymap_info_get(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
932 Eldbus_Message *reply = eldbus_message_method_return_new(msg);
934 eldbus_message_arguments_append(reply, "hi", e_comp_wl->xkb.fd, e_comp_wl->xkb.size);
938 static Eldbus_Message *
939 _e_info_server_cb_fps_info_get(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
941 static double old_fps = 0;
943 Eldbus_Message *reply = eldbus_message_method_return_new(msg);
946 if (!e_comp->calc_fps)
948 e_comp->calc_fps = 1;
951 if (old_fps == e_comp->fps)
953 snprintf(buf, sizeof(buf), "no_update");
955 else if (e_comp->fps > 0.0)
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) ?: " ");
960 snprintf(buf, sizeof(buf), "... FPS %3.1f", e_comp->fps);
961 old_fps = e_comp->fps;
965 snprintf(buf, sizeof(buf), "... FPS N/A");
968 eldbus_message_arguments_append(reply, "s", buf);
972 static Eldbus_Message *
973 e_info_server_cb_transform_message(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
975 Eldbus_Message *reply = eldbus_message_method_return_new(msg);
976 uint32_t enable, transform_id;
977 uint32_t x, y, sx, sy, degree;
979 const char *value = NULL;
980 int32_t value_number;
984 if (!eldbus_message_arguments_get(msg, "siiiiiiii", &value, &transform_id, &enable, &x, &y, &sx, &sy, °ree, &keep_ratio))
986 ERR("Error getting arguments.");
990 if (strlen(value) >= 2 && value[0] == '0' && value[1] == 'x')
991 sscanf(value, "%x", &value_number);
993 sscanf(value, "%d", &value_number);
995 for (o = evas_object_top_get(e_comp->evas); o; o = evas_object_below_get(o))
997 ec = evas_object_data_get(o, "E_Client");
999 E_Info_Transform *transform_info;
1003 win = e_client_util_win_get(ec);
1005 if (win != value_number) continue;
1006 transform_info = _e_info_transform_find(ec, transform_id);
1010 _e_info_transform_set(transform_info, enable, x, y, sx, sy, degree, keep_ratio);
1013 _e_info_transform_del_with_id(ec, transform_id);
1019 _e_info_transform_new(ec, transform_id, enable, x, y, sx, sy, degree, keep_ratio);
1030 _e_info_server_cb_buffer_change(void *data, int type, void *event)
1033 E_Event_Client *ev = event;
1034 Ecore_Window event_win;
1035 char fname[PATH_MAX];
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);
1041 /* dump buffer change call event buffer */
1043 if (e_object_is_del(E_OBJECT(ec)))
1045 ERR("%s: e_object_is_del(E_OBJECT(ec) return\n", __func__);
1046 return ECORE_CALLBACK_PASS_ON;
1048 if (e_client_util_ignored_get(ec))
1050 ERR("%s: e_client_util_ignored_get(ec) true. return\n", __func__);
1051 return ECORE_CALLBACK_PASS_ON;
1053 event_win = e_client_util_win_get(ec);
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);
1062 /* dump all buffers */
1063 char path[PATH_MAX];
1065 snprintf(path, sizeof(path), "%s/%d", e_info_dump_path, count);
1066 if ((mkdir(path, 0755)) < 0)
1068 printf("%s: mkdir '%s' fail\n", __func__, path);
1069 return ECORE_CALLBACK_PASS_ON;
1072 for (o = evas_object_top_get(e_comp->evas); o; o = evas_object_below_get(o))
1074 E_Client *ec = evas_object_data_get(o, "E_Client");
1078 if (e_client_util_ignored_get(ec)) continue;
1080 win = e_client_util_win_get(ec);
1082 snprintf(fname, sizeof(fname), "%s/0x%08x.png", path, win);
1084 e_info_server_dump_client(ec, fname);
1087 DBG("%d, %s dump excute\n", count, fname);
1089 return ECORE_CALLBACK_PASS_ON;
1093 _e_info_server_dump_directory_make(void)
1101 buf = calloc (1, sizeof (struct tm));
1102 EINA_SAFETY_ON_NULL_RETURN_VAL(buf, NULL);
1103 t = localtime_r(&timer, buf);
1107 ERR("fail to get local time\n");
1111 fullpath = (char *)calloc(1, PATH_MAX * sizeof(char));
1115 ERR("fail to alloc pathname memory\n");
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);
1124 if ((mkdir(fullpath, 0755)) < 0)
1126 ERR("%s: mkdir '%s' fail\n", __func__, fullpath);
1134 static Eldbus_Message *
1135 _e_info_server_cb_buffer_dump(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
1137 Eldbus_Message *reply = eldbus_message_method_return_new(msg);
1140 if (!eldbus_message_arguments_get(msg, "i", &start))
1142 ERR("Error getting arguments.");
1148 if (e_info_dump_running == 1)
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)
1155 e_info_dump_running = 0;
1156 e_info_dump_count = 0;
1157 ERR("dump_buffers start fail\n");
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);
1168 if (e_info_dump_running == 0)
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)
1175 free(e_info_dump_path);
1176 e_info_dump_path = NULL;
1178 e_info_dump_count = 0;
1179 e_info_dump_running = 0;
1186 static Eldbus_Message *
1187 e_info_server_cb_hwc_trace_message(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
1189 Eldbus_Message *reply = eldbus_message_method_return_new(msg);
1192 if (!eldbus_message_arguments_get(msg, "i", &onoff))
1194 ERR("Error getting arguments.");
1198 if (onoff == 1 || onoff == 0)
1199 e_comp_hwc_trace_debug(onoff);
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 },
1211 { "dlog", ELDBUS_ARGS({"i", "using dlog"}), NULL, _e_info_server_cb_dlog_switch, 0},
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 },
1224 { "hwc_trace_message", ELDBUS_ARGS({"i", "hwc_trace_message"}), NULL, e_info_server_cb_hwc_trace_message, 0},
1226 { "get_keymap", NULL, ELDBUS_ARGS({"hi", "keymap fd"}), _e_info_server_cb_keymap_info_get, 0},
1227 { NULL, NULL, NULL, NULL, 0 }
1230 static const Eldbus_Service_Interface_Desc iface_desc = {
1231 IFACE, methods, NULL, NULL, NULL, NULL
1235 e_info_server_init(void)
1239 e_info_server.conn = eldbus_connection_get(ELDBUS_CONNECTION_TYPE_SYSTEM);
1240 EINA_SAFETY_ON_NULL_GOTO(e_info_server.conn, err);
1242 e_info_server.iface = eldbus_service_interface_register(e_info_server.conn,
1245 EINA_SAFETY_ON_NULL_GOTO(e_info_server.iface, err);
1247 E_EVENT_INFO_ROTATION_MESSAGE = ecore_event_type_new();
1252 e_info_server_shutdown();
1257 e_info_server_shutdown(void)
1259 if (e_info_server.iface)
1261 eldbus_service_interface_unregister(e_info_server.iface);
1262 e_info_server.iface = NULL;
1265 if (e_info_server.conn)
1267 eldbus_connection_unref(e_info_server.conn);
1268 e_info_server.conn = NULL;
1271 if (e_info_transform_list)
1273 E_Info_Transform *info;
1274 Eina_List *l, *l_next;
1276 EINA_LIST_FOREACH_SAFE(e_info_transform_list, l, l_next, info)
1278 _e_info_transform_del(info);
1281 eina_list_free(e_info_transform_list);
1282 e_info_transform_list = NULL;
1285 if (e_info_dump_running == 1)
1286 tdm_helper_dump_stop();
1287 if (e_info_dump_hdlrs)
1289 E_FREE_LIST(e_info_dump_hdlrs, ecore_event_handler_del);
1290 e_info_dump_hdlrs = NULL;
1292 if (e_info_dump_path)
1294 free(e_info_dump_path);
1295 e_info_dump_path = NULL;
1297 e_info_dump_count = 0;
1298 e_info_dump_running = 0;
1306 e_info_server_dump_client(E_Client *ec, char *fname)
1310 Ecore_Evas *ee = NULL;
1311 Evas_Object *img = NULL;
1314 if (e_client_util_ignored_get(ec)) return;
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;
1321 if (buffer->type == E_COMP_WL_BUFFER_TYPE_SHM)
1323 shmbuffer = wl_shm_buffer_get(buffer->resource);
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);
1331 else if (buffer->type == E_COMP_WL_BUFFER_TYPE_NATIVE)
1333 tbm_surface_info_s surface_info;
1334 tbm_surface_h tbm_surface = wayland_tbm_server_get_surface(NULL, buffer->resource);
1336 memset(&surface_info, 0, sizeof(tbm_surface_info_s));
1337 tbm_surface_map(tbm_surface, TBM_SURF_OPTION_READ, &surface_info);
1339 data = surface_info.planes[0].ptr;
1340 w = surface_info.planes[0].stride/4;
1341 h = surface_info.height;
1345 ERR("Invalid resource:%u", wl_resource_get_id(buffer->resource));
1349 EINA_SAFETY_ON_NULL_GOTO(data, err);
1351 ee = ecore_evas_buffer_new(1, 1);
1352 EINA_SAFETY_ON_NULL_GOTO(ee, err);
1354 img = evas_object_image_add(ecore_evas_get(ee));
1355 EINA_SAFETY_ON_NULL_GOTO(img, err);
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);
1361 if (!evas_object_image_save(img, fname, NULL, "compress=1 quality=100"))
1362 ERR("Cannot save window to '%s'", fname);
1365 #ifdef HAVE_WAYLAND_ONLY
1366 if (data && buffer->type == E_COMP_WL_BUFFER_TYPE_NATIVE)
1368 tbm_surface_h tbm_surface = wayland_tbm_server_get_surface(NULL, buffer->resource);
1369 tbm_surface_unmap(tbm_surface);
1373 if (img) evas_object_del(img);
1374 if (ee) ecore_evas_free(ee);
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)
1381 E_Info_Transform *result = NULL;
1382 result = _e_info_transform_find(ec, id);
1386 result = (E_Info_Transform*)malloc(sizeof(E_Info_Transform));
1387 memset(result, 0, sizeof(E_Info_Transform));
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);
1399 static E_Info_Transform*
1400 _e_info_transform_find(E_Client *ec, int id)
1403 E_Info_Transform *transform;
1404 E_Info_Transform *result = NULL;
1406 EINA_LIST_FOREACH(e_info_transform_list, l, transform)
1408 if (transform->ec == ec && transform->id == id)
1419 _e_info_transform_set(E_Info_Transform *transform, int enable, int x, int y, int sx, int sy, int degree, int keep_ratio)
1421 if (!transform) return;
1422 if (!transform->transform) return;
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);
1430 e_client_transform_core_add(transform->ec, transform->transform);
1432 e_client_transform_core_remove(transform->ec, transform->transform);
1434 e_client_transform_core_update(transform->ec);
1438 _e_info_transform_del(E_Info_Transform *transform)
1440 if (!transform) return;
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);
1449 _e_info_transform_del_with_id(E_Client *ec, int id)
1451 E_Info_Transform *transform = NULL;
1454 transform = _e_info_transform_find(ec, id);
1457 _e_info_transform_del(transform);