Initialize Tizen 2.3
[kernel/api/system-resource.git] / src / proc-stat / proc-winstate.c
1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <string.h>
4 #include <resourced.h>
5
6 #include "proc-winstate.h"
7 #include "proc-main.h"
8 #include "proc-process.h"
9 #include "proc-monitor.h"
10 #include "trace.h"
11
12 #include <X11/Xlib.h>
13 #include <X11/Xatom.h>
14 #include <Ecore.h>
15 #include <Ecore_X.h>
16 #include <Ecore_Evas.h>
17 #include <Ecore_Input_Evas.h>
18
19 static Atom a_pid;
20
21 typedef struct  _ProcWininfo {
22     struct _ProcWininfo *prev, *next;
23     int idx;
24     long pid;
25     Window winid;
26 } ProcWininfo, *ProcWininfoPtr;
27
28 static pid_t __get_win_pid(Display *d, Window win)
29 {
30         int r;
31         pid_t pid;
32
33         Atom a_type;
34         int format;
35         unsigned long nitems;
36         unsigned long bytes_after;
37         unsigned char *prop_ret;
38         XWindowAttributes attr;
39
40         //_retv_if(d == NULL || !a_pid, -1);
41
42         if (!XGetWindowAttributes(d, win, &attr))
43                 return -1;
44
45         if (attr.override_redirect || attr.class == InputOnly)
46                 return -1;
47
48         prop_ret = NULL;
49         r = XGetWindowProperty(d, win, a_pid, 0, 1, False, XA_CARDINAL,
50                                &a_type, &format, &nitems, &bytes_after,
51                                &prop_ret);
52         if (r != Success || prop_ret == NULL)
53                 return -1;
54
55         if (a_type == XA_CARDINAL && format == 32)
56                 pid = *(unsigned long *)prop_ret;
57         else
58                 pid = -1;
59
60         XFree(prop_ret);
61
62         return pid;
63 }
64
65 static Window get_window(Display *d, Window win)
66 {
67         Atom type_ret = 0;
68         int ret, size_ret = 0;
69         unsigned long num_ret = 0, bytes = 0;
70         unsigned char *prop_ret = NULL;
71         unsigned int xid;
72         Atom prop_user_created_win;
73
74         prop_user_created_win = XInternAtom(d, "_E_USER_CREATED_WINDOW", False);
75
76         ret = XGetWindowProperty(d, win, prop_user_created_win, 0L, 1L,
77             False, XA_WINDOW, &type_ret, &size_ret,
78             &num_ret, &bytes, &prop_ret);
79
80         if( ret != Success )
81         {
82                 if( prop_ret ) XFree( (void*)prop_ret );
83                 return win;
84         }
85         else if( !prop_ret )
86         {
87                 return win;
88         }
89
90         memcpy( &xid, prop_ret, sizeof(unsigned int) );
91         XFree( (void *)prop_ret );
92
93         return xid;
94 }
95
96 static void free_procwininfo(ProcWininfoPtr procwininfo)
97 {
98         ProcWininfoPtr w;
99 /* TODO : free winname and appname map_state*/
100         w = procwininfo;
101         if (!w)
102                 return;
103         while(1)
104         {
105                 if(w && w->next)
106                         w = w->next;
107                 else
108                         break;
109         }
110         while(1)
111         {
112                 if(w && w->prev)
113                 {
114                         w = w->prev;
115                         free(w->next);
116                 }
117                 else
118                 {
119                         if(w)
120                                 free(w);
121                         break;
122                 }
123         }
124 }
125
126
127 static int __find_win(Display *d, pid_t pid)
128 {
129         int r, i, found = 0;
130         pid_t p;
131         unsigned int n;
132         int win_index = 0, winid = 0;
133         Window root, parent, *child;
134         Window win;
135         ProcWininfoPtr prev_wininfo = NULL;
136         ProcWininfoPtr cur_wininfo = NULL;
137         ProcWininfoPtr origin_wininfo = NULL;
138         XWindowAttributes attr;
139
140         win = XDefaultRootWindow(d);
141
142         r = XQueryTree(d, win, &root, &parent, &child, &n);
143         if (!r) {
144                 _E("Can't query window tree.");
145                 return 0;
146         }
147
148         for (i = (int)n - 1; i >= 0; i--)
149         {
150                 if (!XGetWindowAttributes(d, child[i], &attr)) {
151                         _E("Can't get window tree.");
152                         continue;
153                 }
154                 if (attr.map_state) {
155                         cur_wininfo = (ProcWininfoPtr) malloc(sizeof(ProcWininfo));
156                         cur_wininfo->idx = win_index++;
157                         cur_wininfo->next = NULL;
158                         cur_wininfo->prev = NULL;
159                         cur_wininfo->winid = child[i];
160                 } else
161                         continue;
162                 if(prev_wininfo)
163                 {
164                         prev_wininfo->next = cur_wininfo;
165                         cur_wininfo->prev = prev_wininfo;
166                 } else
167                         origin_wininfo = cur_wininfo;
168
169                 /* set the pre_wininfo is the cur_wininfo now */
170                 prev_wininfo = cur_wininfo;
171         }
172         if (!origin_wininfo) {
173                 _E("Can't get valid window info");
174                 if (child)
175                         XFree((char *)child);
176                 return 0;
177         }
178
179         ProcWininfoPtr w = origin_wininfo;
180         for(i = 0; i < win_index; i++)
181         {
182                 winid = get_window(d, w->winid);
183                 w->winid = winid;
184                 p = __get_win_pid(d, w->winid);
185                 if (p == pid) {
186                         found++;
187                         _D("__find_win : pid %d, win %x", pid, w->winid);
188                         ecore_x_window_client_sniff(w->winid);
189                 }
190                 w = w->next;
191         }
192         if (child)
193                 XFree((char *)child);
194         free_procwininfo(origin_wininfo);
195         return 0;
196 }
197
198 static inline int _get_pid(Ecore_X_Window win)
199 {
200         int pid;
201         Ecore_X_Atom atom;
202         unsigned char *in_pid = NULL;
203         int num;
204
205         atom = ecore_x_atom_get("X_CLIENT_PID");
206         if (ecore_x_window_prop_property_get(win, atom, ECORE_X_ATOM_CARDINAL,
207                                 sizeof(int), &in_pid, &num) == EINA_FALSE) {
208                 if(in_pid != NULL) {
209                         free(in_pid);
210                         in_pid = NULL;
211                 }
212                 if (ecore_x_netwm_pid_get(win, &pid) == EINA_FALSE) {
213                         _E("Failed to get PID from a window 0x%X", win);
214                         return -EINVAL;
215                 }
216         } else {
217                 pid = *(int *)in_pid;
218                 free(in_pid);
219         }
220
221         return pid;
222 }
223
224 static Eina_Bool __proc_deiconify_cb(void *data, int type, void *event)
225 {
226         Ecore_X_Event_Client_Message *ev;
227         int pid, oom_score_adj;
228
229         ev = event;
230
231         if (ev->format != 32)
232                 return ECORE_CALLBACK_RENEW;
233         if (ev->message_type == ECORE_X_ATOM_E_DEICONIFY_APPROVE)
234         {
235                 pid = _get_pid(ev->win);
236
237                 _D("pid : %d received ediconify approve", pid);
238
239                 if (proc_get_oom_score_adj(pid, &oom_score_adj) < 0) {
240                         _E("Failed to get oom_score_adj");
241                         return ECORE_CALLBACK_RENEW;
242                 }
243
244                 if (oom_score_adj >= OOMADJ_BACKGRD_UNLOCKED) {
245                         /* init oom_score_value */
246                         proc_set_oom_score_adj(pid, OOMADJ_INIT);
247                 }
248         }
249
250         return ECORE_CALLBACK_RENEW;
251
252 }
253
254 static Eina_Bool __proc_visibility_cb(void *data, int type, void *event)
255 {
256         Ecore_X_Event_Window_Visibility_Change *ev;
257         int pid, oom_score_adj;
258
259         ev = event;
260
261         pid = _get_pid(ev->win);
262
263         _D("pid : %d, bvisibility : %d", pid, ev->fully_obscured);
264
265         if (proc_get_oom_score_adj(pid, &oom_score_adj) < 0) {
266                 _E("Failed to get oom_score_adj");
267                 return ECORE_CALLBACK_RENEW;
268         }
269
270         if (oom_score_adj >= OOMADJ_BACKGRD_UNLOCKED) {
271                 /* init oom_score_value */
272                 proc_set_oom_score_adj(pid, OOMADJ_INIT);
273         }
274
275         return ECORE_CALLBACK_RENEW;
276
277 }
278
279 int proc_add_visibiliry(int pid)
280 {
281         int found;
282         Display *d;
283
284         if (proc_get_dbus_proc_state())
285                 return RESOURCED_ERROR_NO_DATA;
286         d = XOpenDisplay(NULL);
287
288         if (d == NULL) {
289                 _E("XOpenDisplay return NULL, pid = %d", pid);
290                 return RESOURCED_ERROR_FAIL;
291         }
292
293         if (!a_pid)
294                 a_pid = XInternAtom(d, "_NET_WM_PID", True);
295
296         found = __find_win(d, pid);
297
298         if (!found) {
299                 XCloseDisplay(d);
300                 errno = ENOENT;
301                 return RESOURCED_ERROR_FAIL;
302         } else
303                 _D("%d window added for pid = %d", found, pid);
304
305         return RESOURCED_ERROR_NONE;
306 }
307
308
309 int proc_win_status_init(void)
310 {
311         ecore_x_init(NULL);
312         ecore_event_handler_add(ECORE_X_EVENT_CLIENT_MESSAGE,
313                                     __proc_deiconify_cb, NULL);
314
315         ecore_event_handler_add(ECORE_X_EVENT_WINDOW_VISIBILITY_CHANGE,
316                                     __proc_visibility_cb, NULL);
317         return RESOURCED_ERROR_NONE;
318 }
319