1 /**************************************************************************
4 Copyright 2014 Samsung Electronics co., Ltd. All Rights Reserved.
6 Contact: SooChan Lim <sc1.lim@samsung.com>
8 Permission is hereby granted, free of charge, to any person obtaining a
9 copy of this software and associated documentation files (the
10 "Software"), to deal in the Software without restriction, including
11 without limitation the rights to use, copy, modify, merge, publish,
12 distribute, sub license, and/or sell copies of the Software, and to
13 permit persons to whom the Software is furnished to do so, subject to
14 the following conditions:
16 The above copyright notice and this permission notice (including the
17 next paragraph) shall be included in all copies or substantial portions
20 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
23 IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
24 ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
25 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
26 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 **************************************************************************/
31 #include <X11/Xutil.h>
32 #include <X11/Xatom.h>
35 #include <X11/Xlocale.h>
45 static void Display_Window_Id(FILE* fd, Window window, Bool newline_wanted);
46 static void Display_Pointed_Window_Info(FILE* fd);
47 static void Display_Focused_Window_Info(FILE* fd);
56 static const char *window_id_format = "0x%lx";
57 static int win_cnt = 0;
65 static const binding _map_states[] = {
66 { IsUnmapped, "IsUnMapped" },
67 { IsUnviewable, "IsUnviewable" },
68 { IsViewable, "IsViewable" },
71 typedef struct _Wininfo {
72 struct _Wininfo *prev, *next;
74 /*" PID WinID w h Rel_x Rel_y Abs_x Abs_y Depth WinName App_Name*/
90 } Wininfo, *WininfoPtr;
93 * Standard fatal error routine - call like printf
94 * Does not require dpy or screen defined.
96 void Fatal_Error(const char *msg, ...)
102 vfprintf(stderr, msg, args);
104 fprintf(stderr, "\n");
109 Display_Pointed_Window_Info(FILE* fd)
111 int rel_x, rel_y, abs_x, abs_y;
112 Window root_win, pointed_win;
115 XQueryPointer(dpy, RootWindow(dpy, 0), &root_win, &pointed_win, &abs_x,
116 &abs_y, &rel_x, &rel_y, &mask);
120 Display_Window_Id(fd, pointed_win, True);
124 fprintf(fd, "no pointed window\n");
131 Display_Focused_Window_Info(FILE* fd)
136 XGetInputFocus( dpy, &focus_win, &revert_to);
140 Display_Window_Id(fd, focus_win, True);
146 Display_Window_Id(FILE* fd, Window window, Bool newline_wanted)
153 fprintf(fd, "[winID:");
154 fprintf(fd, window_id_format, window); /* print id # in hex/dec */
157 fprintf(fd, " (none)");
159 if (window == RootWindow(dpy, screen)) {
160 fprintf(fd, " (the root window)");
163 if (!XFetchName(dpy, window, &win_name)) { /* Get window name if any */
164 fprintf(fd, " (has no name)");
165 } else if (win_name) {
166 fprintf(fd, " \"%s\"", win_name);
170 if (!XGetWMName(dpy, window, &tp)) { /* Get window name if any */
171 fprintf(fd, " (has no name)");
172 } else if (tp.nitems > 0) {
175 int count = 0, i, ret;
177 ret = XmbTextPropertyToTextList(dpy, &tp, &list, &count);
178 if((ret == Success || ret > 0) && list != NULL){
179 for(i=0; i<count; i++)
180 fprintf(fd, "%s", list[i]);
181 XFreeStringList(list);
183 fprintf(fd, "%s", tp.value);
190 fprintf(fd, " (has no name)");
203 wininfo = (WininfoPtr) malloc(sizeof(Wininfo));
206 fprintf(stderr, " alloc error \n");
209 wininfo->idx = win_cnt++;
210 wininfo->next = NULL;
211 wininfo->prev = NULL;
216 free_wininfo(WininfoPtr wininfo)
219 /* TODO : free winname and appname map_state*/
251 get_winname(Window window, char* str)
256 unsigned long nitems, bytes_after;
257 char *class_name = NULL;
262 if (window == RootWindow(dpy, screen))
264 printf(" (the root window)");
267 if (XGetWMName(dpy, window, &tp))
271 int count = 0, i, ret;
273 ret = XmbTextPropertyToTextList(dpy, &tp, &list, &count);
274 if((ret == Success || ret > 0) && list != NULL)
276 for(i=0; i<count; i++)
277 snprintf(str, 255, "%s", *list);
278 XFreeStringList(list);
282 else if (XGetWindowProperty(dpy, window, prop_class,
284 False, AnyPropertyType,
285 &actual_type, &actual_format, &nitems,
286 &bytes_after, (unsigned char **)&class_name) == Success
287 && nitems && class_name != NULL)
289 strncpy(str, class_name, strlen(class_name)+1);
302 get_appname_brief(char* brief)
306 char temp[255] = {0,};
309 token = strtok_r(brief, delim, &tokp);
310 while (token != NULL) {
311 memset(temp, 0x00, 255*sizeof(char));
312 strncpy(temp, token, 255*sizeof(char)-1);
314 token = strtok_r(NULL, delim, &tokp);
317 snprintf(brief, 255, "%s", temp);
321 get_appname_from_pid(long pid, char* str)
326 char fn_cmdline[255] = {0,};
327 char cmdline[255] = {0,};
329 snprintf(fn_cmdline, 255,"/proc/%ld/cmdline",app_pid);
331 fp = fopen(fn_cmdline, "r");
334 fprintf(stderr,"cannot file open /proc/%ld/cmdline", app_pid);
337 if (!fgets(cmdline, 255, fp)) {
338 fprintf(stderr,"cannot fgets /proc/%ld/cmdline", app_pid);
342 len = strlen(cmdline);
344 memset(cmdline, 0x00,255);
349 if(strstr(cmdline, "app-domain") != NULL)
351 char temp_buf[255] = {0,};
353 memset(fn_cmdline, 0x00, 255);
354 snprintf(fn_cmdline, 255, "/proc/%ld/maps", app_pid);
355 fp = fopen(fn_cmdline, "r");
358 fprintf(stderr,"cannot file open /proc/%ld/maps", app_pid);
364 fgets(temp_buf, 255, fp);
365 if(!(buf = strstr(temp_buf, "/com.samsung")))
368 buf = strstr(buf, "/lib");
370 if(buf[strlen(buf)-1] == '\n')
371 buf[strlen(buf)-4] = 0;
373 memset(cmdline, 0x00, 255);
374 strncpy(cmdline, buf, strlen(buf)+1);
383 snprintf(str, 255, "%s", cmdline);
387 * Lookup: lookup a code in a table.
389 static char _lookup_buffer[100];
392 LookupL(long code, const binding *table)
396 snprintf(_lookup_buffer, sizeof(_lookup_buffer),
397 "unknown (code = %ld. = 0x%lx)", code, code);
398 name = _lookup_buffer;
400 while (table->name) {
401 if (table->code == code) {
412 Lookup(int code, const binding *table)
414 return LookupL((long)code, table);
418 get_map_status(Window window)
420 XWindowAttributes win_attributes;
422 if (!XGetWindowAttributes(dpy, window, &win_attributes))
423 printf("Can't get window attributes.");
425 if( win_attributes.map_state == 0 )
428 return win_attributes.map_state;
431 static int Ping_Event_Loop()
435 while (XPending (dpy)) {
438 /* draw or redraw the window */
439 if (e.type == Expose) {
440 fprintf(stderr," Expose \n");
442 /* exit on key press */
443 if (e.type == KeyPress) {
444 fprintf(stderr," KeyPress \n");
447 if (e.type == ClientMessage ) {
455 Send_Ping_to_Window(Window window)
457 XClientMessageEvent xclient;
458 Display* display = dpy;
460 memset (&xclient, 0, sizeof (xclient));
461 xclient.type = ClientMessage;
462 xclient.window = window;
464 xclient.message_type = XInternAtom (display, "WM_PROTOCOLS",0);
468 xclient.data.l[0] = XInternAtom (display, "_NET_WM_PING",0);
469 xclient.data.l[1] = 0;
470 // fprintf(stderr,"<0x%x>\n", window);
471 XSendEvent (display, window, 0,
480 void print_default(FILE* fd, Window root_win, int num_children)
483 fprintf(fd, " Root window id :");
484 Display_Window_Id(fd, root_win, True);
485 fprintf(fd, " Pointed window :");
486 Display_Pointed_Window_Info(fd);
487 fprintf(fd, " Input Focused window :");
488 Display_Focused_Window_Info(fd);
490 fprintf(fd, "%d Top level windows\n", num_children);
493 void gen_output(XinfoPtr pXinfo, WininfoPtr pWininfo)
499 int val = pXinfo->xinfo_val;
500 WininfoPtr w = pWininfo;
501 char* name = pXinfo->xinfovalname;
502 char* path = pXinfo->pathname;
503 char* file = pXinfo->filename;
505 char *argument_props_root[3];
506 char *argument_props_id[4];
509 Window root_win = RootWindow(dpy, screen);
510 int num_children = win_cnt;
512 argument[2] = (char *)malloc(sizeof(char)*15);
513 argument[4] = (char *)malloc(sizeof(char)*255);
515 argument[0] = strdup("xwd");
516 argument[1] = strdup("-id");
517 argument[3] = strdup("-out");
520 fd = pXinfo->output_fd;
521 fprintf(stderr, "[%s] Start to logging ", name);
523 fprintf(stderr, "at %s/%s\n", path, file);
525 fprintf(stderr, "\n");
526 if(val == XINFO_TOPWINS)
528 print_default(fd, root_win, num_children);
529 fprintf( fd, "----------------------------------[ %s ]-------------------------------------------------------------------------------\n", name);
530 fprintf( fd, " No PID WinID w h Rel_x Rel_y Abs_x Abs_y Depth WinName AppName\n" );
531 fprintf( fd, "----------------------------------------------------------------------------------------------------------------------------\n" );
533 for(i = 0; i < win_cnt; i++)
535 fprintf(fd, "%3i %6ld 0x%-7lx %4i %4i %5i %5i %5i %5i %5i %-35s %-35s\n",
536 (w->idx+1),w->pid,w->winid,w->w,w->h,w->rel_x,w->rel_y,w->abs_x,w->abs_y,w->depth,w->winname,w->appname_brief);
541 else if(val == XINFO_TOPVWINS)
543 print_default(fd, root_win, num_children);
544 fprintf( fd, "----------------------------------[ %s ]------------------------------------------------------------------------------------------------\n", name);
545 fprintf( fd, " No PID BorderID WinID w h Rel_x Rel_y Abs_x Abs_y Depth WinName AppName map state \n" );
546 fprintf( fd, "----------------------------------------------------------------------------------------------------------------------------------------------\n" );
548 for(i = 0; i < win_cnt; i++)
550 fprintf( fd, "%3i %6ld 0x%-7lx 0x%-8lx %4i %4i %5i %5i %5i %5i %5i %-25s %-25s %-30s\n",
551 (w->idx+1),w->pid,w->BDid,w->winid,w->w,w->h,w->rel_x,w->rel_y,w->abs_x,w->abs_y,w->depth,w->winname, w->appname_brief,w->map_state);
556 else if(val == XINFO_TOPVWINS_PROPS)
558 print_default(fd, root_win, num_children);
560 fprintf( fd, "###[ Root Window ]###\n");
561 fprintf( fd, "ID: 0x%lx\n", root_win);
562 fprintf( fd, "######\n" );
563 argument_props_root[0] = strdup("/usr/bin/xprop");
564 argument_props_root[1] = strdup("-root");
565 argument_props_root[2] = NULL;
570 if (execv("/usr/bin/xprop", argument_props_root) == -1)
572 fprintf(fd, "failed to excute 'xprop -root'\n");
579 waitpid(pid, &child_status, WUNTRACED);
582 argument_props_id[0] = strdup("/usr/bin/xprop");
583 argument_props_id[1] = strdup("-id");
584 argument_props_id[2] = (char *)malloc(sizeof(char)*15);
585 argument_props_id[3] = NULL;
586 for(i = 0; i < win_cnt; i++)
588 fprintf( fd, "\n###[ Window ID: 0x%x ]###\n", (unsigned int)w->winid);
589 fprintf( fd, "PID: %ld\n", w->pid);
590 fprintf( fd, "Border ID: 0x%x\n", (unsigned int)w->BDid);
591 fprintf( fd, "###\n" );
592 snprintf(argument_props_id[2], 15, "0x%-7x", (unsigned int)w->BDid);
597 if (execv("/usr/bin/xprop", argument_props_id) == -1)
599 fprintf(stderr, "failed to excute 'xprop' \n");
606 waitpid(pid, &child_status, WUNTRACED);
608 fprintf( fd, "###\n" );
609 fprintf( fd, "Win Name : %s\n", w->winname);
610 fprintf( fd, "Window ID: 0x%x\n", (unsigned int)w->winid);
611 fprintf( fd, "######\n" );
612 snprintf(argument_props_id[2], 15, "0x%-7x", (unsigned int)w->winid);
617 if (execv("/usr/bin/xprop", argument_props_id) == -1)
619 fprintf(stderr, "failed to excute 'xprop' \n");
626 waitpid(pid, &child_status, WUNTRACED);
628 fprintf( fd, "######\n" );
632 free(argument_props_id[0]);
633 free(argument_props_id[1]);
634 free(argument_props_id[2]);
636 free(argument_props_root[0]);
637 free(argument_props_root[1]);
639 else if(val == XINFO_PING)
641 print_default(fd, root_win, num_children);
642 fprintf( fd, "----------------------------------[ %s ]-----------------------------------------------------------------------------------------------------\n", name);
643 fprintf( fd, " No PID WinID w h WinName AppName Ping Command\n" );
644 fprintf( fd, "-----------------------------------------------------------------------------------------------------------------------------------------------\n" );
646 for(i = 0; i < win_cnt; i++)
648 fprintf( fd, "%3i %6ld 0x%-7lx %4i %4i %-30s %-30s %-20s %-40s\n",
649 (w->idx+1),w->pid,w->winid,w->w,w->h, w->winname, w->appname_brief,w->ping_result,w->appname);
654 else if(val == XINFO_XWD_TOPVWINS)
656 fprintf( stderr, " [START] %s : the path to store the xwd files is %s \n", name, path);
658 /* dump root window */
659 snprintf(argument[2], 15,"0x%-7lx", root_win);
660 snprintf(argument[4], 255,"%s/root_win.xwd", path);
665 if (execv("/usr/bin/xwd", argument) == -1)
667 fprintf(stderr, "execv error root xwd\n");
675 for(i = 0; i < win_cnt; i++)
677 snprintf(argument[2], 15, "0x%-7lx", w->winid);
678 snprintf(argument[4], 255, "%s/0x%-7lx.xwd", path, w->winid);
683 if (execv("/usr/bin/xwd", argument) == -1)
685 fprintf(stderr, "execv error other xwd\n");
694 fprintf( stderr, " [FINISH] %s : the path to store the xwd files is %s \n", name, path);
696 else if(val == XINFO_XWD_WIN)
698 fprintf( stderr, " [START] %s : the path to store the xwd files is %s \n", name, path);
700 snprintf(argument[2], 15, "0x%-7x", pXinfo->win);
701 snprintf(argument[4], 255, "%s/0x%-7x.xwd", path, pXinfo->win);
706 if (execv("/usr/bin/xwd", argument) == -1)
708 fprintf(stderr, "execv error window xwd\n");
715 fprintf( stderr, " [FINISH] %s : the path to store the xwd files is %s \n", name, path);
717 fprintf(stderr, "[%s] Finish to logging ", name);
719 fprintf(stderr, "at %s/%s\n", path, file);
721 fprintf(stderr, "\n");
734 static Window get_user_created_window(Window win)
738 int ret, size_ret = 0;
739 unsigned long num_ret = 0, bytes = 0;
740 unsigned char *prop_ret = NULL;
742 Atom prop_user_created_win;
744 prop_user_created_win = XInternAtom(dpy, "_E_USER_CREATED_WINDOW", False);
746 ret = XGetWindowProperty(dpy, win, prop_user_created_win, 0L, 1L,
747 False, XA_WINDOW, &type_ret, &size_ret,
748 &num_ret, &bytes, &prop_ret);
752 if( prop_ret ) XFree( (void*)prop_ret );
760 memcpy( &xid, prop_ret, sizeof(unsigned int) );
761 XFree( (void *)prop_ret );
768 static int cb_x_error(Display *disp, XErrorEvent *ev)
775 display_topwins(XinfoPtr pXinfo)
778 int rel_x, rel_y, abs_x, abs_y;
779 unsigned int width, height, border, depth;
780 Window root_win, parent_win;
781 unsigned int num_children;
784 // char *command_name = NULL;
785 // char *class_name = NULL;
788 unsigned long nitems, bytes_after;
791 int wininfo_val = pXinfo->xinfo_val;
793 /* open a display and get a default screen */
794 dpy = XOpenDisplay(0);
797 printf("Fail to open display\n");
802 screen = DefaultScreen(dpy);
804 /* get a root window id */
805 window = RootWindow(dpy, screen);
807 // /* set a error handler */
808 // m_old_error = XSetErrorHandler(cb_x_error);
810 if(wininfo_val == XINFO_PING)
811 XSelectInput (dpy, window, ExposureMask| SubstructureNotifyMask);
813 /* XINFO_XWD_WIN do not need to gethering window information */
814 if(wininfo_val == XINFO_XWD_WIN)
816 gen_output(pXinfo, NULL);
820 /* query a window tree */
821 if (!XQueryTree(dpy, window, &root_win, &parent_win, &child_list, &num_children))
822 Fatal_Error("Can't query window tree.");
824 /* get a properties */
825 prop_pid = XInternAtom(dpy, "_NET_WM_PID", False);
826 prop_c_pid = XInternAtom(dpy, "X_CLIENT_PID", False);
827 prop_class = XInternAtom(dpy, "WM_CLASS", False);
828 prop_command = XInternAtom(dpy, "WM_COMMAND", False);
830 /* gathering the wininfo infomation */
831 WininfoPtr prev_wininfo = NULL;
832 WininfoPtr cur_wininfo = NULL;
833 WininfoPtr origin_wininfo = NULL;
836 /* Make the wininfo list */
837 for (i = (int)num_children - 1; i >= 0; i--)
839 if(wininfo_val == XINFO_TOPVWINS || wininfo_val == XINFO_XWD_TOPVWINS || wininfo_val == XINFO_TOPVWINS_PROPS)
841 /* figure out whether the window is mapped or not */
842 map_state = get_map_status(child_list[i]);
847 cur_wininfo = alloc_wininfo();
848 cur_wininfo->map_state = (char*) calloc(1, 255*sizeof(char));
849 snprintf(cur_wininfo->map_state, 255, " %s ", Lookup(map_state, _map_states));
852 cur_wininfo->winid = child_list[i];
853 cur_wininfo->BDid = child_list[i];
856 else if(wininfo_val == XINFO_TOPWINS || wininfo_val == XINFO_PING)
858 cur_wininfo = alloc_wininfo();
861 cur_wininfo->winid = child_list[i];
862 cur_wininfo->BDid = child_list[i];
866 printf("Error . no valid win_state\n");
872 prev_wininfo->next = cur_wininfo;
873 cur_wininfo->prev = prev_wininfo;
876 origin_wininfo = cur_wininfo;
878 /* set the pre_wininfo is the cur_wininfo now */
879 prev_wininfo = cur_wininfo;
882 if (origin_wininfo == NULL)
885 /* check the window generated in client side not is done by window manager */
886 WininfoPtr w = origin_wininfo;
888 for(i = 0; i < win_cnt; i++)
890 winid = get_user_created_window(w->winid);
893 /* move to the next wininfo */
898 /* check other infomation out */
900 for(i = 0; i < win_cnt; i++)
903 if (XGetWindowProperty(dpy, w->winid, prop_pid,
906 &actual_type, &actual_format, &nitems,
907 &bytes_after, (unsigned char **)&pid) == Success
908 && nitems && pid != NULL)
912 else if (XGetWindowProperty(dpy, w->winid, prop_c_pid,
915 &actual_type, &actual_format, &nitems,
916 &bytes_after, (unsigned char **)&pid) == Success
917 && nitems && pid != NULL)
927 /* get the geometry info and depth*/
928 if (XGetGeometry(dpy, w->winid, &root_win, &rel_x, &rel_y, &width, &height, &border, &depth))
935 if (XTranslateCoordinates (dpy, w->winid, root_win, 0 ,0, &abs_x, &abs_y, &child))
937 w->abs_x = abs_x -border;
938 w->abs_y = abs_y - border;
945 /* get the winname */
946 w->winname = (char*) calloc(1, 255*sizeof(char));
947 get_winname(w->winid, w->winname);
949 /* get app_name from WM_COMMAND or WM_CLASS */
950 w->appname = (char*) calloc(1, 255*sizeof(char));
951 if (XGetWindowProperty(dpy, w->winid, prop_command,
953 False, AnyPropertyType,
954 &actual_type, &actual_format, &nitems,
955 &bytes_after, (unsigned char **)&command_name) == Success
956 && nitems && command_name != NULL)
958 strncpy(w->appname, command_name, strlen(command_name)+1);
962 if (XGetWindowProperty(dpy, w->winid, prop_class,
964 False, AnyPropertyType,
965 &actual_type, &actual_format, &nitems,
966 &bytes_after, (unsigned char **)&class_name) == Success
967 && nitems && class_name != NULL)
969 strncpy(w->appname, class_name, strlen(class_name)+1);
990 w->appname_brief = (char*) calloc(1, 255*sizeof(char));
992 strncpy(w->appname_brief, w->appname, 255*sizeof(char)-1);
994 get_appname_brief (w->appname_brief);
997 /* get app_name from pid */
1000 w->appname = (char*) calloc(1, 255*sizeof(char));
1001 get_appname_from_pid(w->pid, w->appname);
1003 w->appname_brief = (char*) calloc(1, 255*sizeof(char));
1004 strncpy(w->appname_brief, w->appname, 255*sizeof(char)-1);
1005 get_appname_brief (w->appname_brief);
1016 /* ping test info */
1017 if(wininfo_val == XINFO_PING)
1019 Send_Ping_to_Window(w->winid);
1021 w->ping_result = (char*) calloc(1, 255*sizeof(char));
1022 if(Ping_Event_Loop())
1023 snprintf(w->ping_result, 255, " Success ");
1025 snprintf(w->ping_result, 255, " Fail ");
1028 /* move to the next wininfo */
1035 gen_output(pXinfo, origin_wininfo);
1038 XFree((char *)child_list);
1040 free_wininfo(origin_wininfo);