tizen 2.4 release
[framework/appfw/app-core.git] / src / appcore-X.c
1 /*
2  *  app-core
3  *
4  * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Jayoun Lee <airjany@samsung.com>, Sewook Park <sewook7.park@samsung.com>, Jaeho Lee <jaeho81.lee@samsung.com>
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  */
21
22
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <errno.h>
27 #include <signal.h>
28
29 #include <X11/Xlib.h>
30 #include <X11/Xatom.h>
31 #include <Ecore.h>
32
33 #include "appcore-internal.h"
34
35 static Atom a_pid;
36 static Atom a_active_win;
37
38 static pid_t __get_win_pid(Display *d, Window win)
39 {
40         int r;
41         pid_t pid;
42
43         Atom a_type;
44         int format;
45         unsigned long nitems;
46         unsigned long bytes_after;
47         unsigned char *prop_ret;
48         XWindowAttributes attr;
49
50         _retv_if(d == NULL || !a_pid, -1);
51
52         if (!XGetWindowAttributes(d, win, &attr))
53                 return -1;
54
55         if (attr.override_redirect || attr.class == InputOnly)
56                 return -1;
57
58         prop_ret = NULL;
59         r = XGetWindowProperty(d, win, a_pid, 0, 1, False, XA_CARDINAL,
60                                &a_type, &format, &nitems, &bytes_after,
61                                &prop_ret);
62         if (r != Success || prop_ret == NULL)
63                 return -1;
64
65         if (a_type == XA_CARDINAL && format == 32)
66                 pid = *(unsigned long *)prop_ret;
67         else
68                 pid = -1;
69
70         XFree(prop_ret);
71
72         return pid;
73 }
74
75 static int __find_win(Display *d, Window *win, pid_t pid)
76 {
77         int r;
78         pid_t p;
79         unsigned int n;
80         Window root, parent, *child;
81
82         p = __get_win_pid(d, *win);
83         if (p == pid)
84                 return 1;
85
86         r = XQueryTree(d, *win, &root, &parent, &child, &n);
87         if (r) {
88                 int i;
89                 int found = 0;
90
91                 for (i = 0; i < n; i++) {
92                         found = __find_win(d, &child[i], pid);
93                         if (found) {
94                                 *win = child[i];
95                                 break;
96                         }
97                 }
98                 XFree(child);
99
100                 if (found)
101                         return 1;
102         }
103
104         return 0;
105 }
106
107 static void __add_win_list(Eina_List **list, Window *win)
108 {
109         void *w;
110         Eina_List *l;
111
112         if (!list || !win)
113                 return;
114
115         EINA_LIST_FOREACH(*list, l, w) {
116                 if ((Window)w == *win)
117                         return;
118         }
119
120         *list = eina_list_append(*list, (void *)*win);
121 }
122
123 static void __foreach_win(Eina_List **list, Display *d, Window *win, pid_t pid)
124 {
125         int i;
126         int r;
127         pid_t p;
128         unsigned int n;
129         Window root, parent, *child;
130
131         p = __get_win_pid(d, *win);
132         if (p == pid)
133                 __add_win_list(list, win);
134
135         r = XQueryTree(d, *win, &root, &parent, &child, &n);
136         if (r) {
137                 for (i = 0; i < n; i++) {
138                         __foreach_win(list, d, &child[i], pid);
139                 }
140                 XFree(child);
141         }
142 }
143
144 static int __iconify_win(Eina_List *list, Display *d)
145 {
146         void *w;
147         Eina_List *l;
148
149         if (!list || !d)
150                 return -1;
151
152         EINA_LIST_FOREACH(list, l, w) {
153                 XIconifyWindow(d, (Window)w, 0);
154         }
155
156         return 0;
157 }
158
159 static int __raise_win(Display *d, Window win)
160 {
161         XEvent xev;
162         Window root;
163
164         if (!a_active_win)
165                 a_active_win = XInternAtom(d, "_NET_ACTIVE_WINDOW", False);
166
167         root = XDefaultRootWindow(d);
168
169         xev.xclient.type = ClientMessage;
170         xev.xclient.display = d;
171         xev.xclient.window = win;
172         xev.xclient.message_type = a_active_win;
173         xev.xclient.format = 32;
174         xev.xclient.data.l[0] = 1;
175         xev.xclient.data.l[1] = CurrentTime;
176         xev.xclient.data.l[2] = 0;
177         xev.xclient.data.l[3] = 0;
178         xev.xclient.data.l[4] = 0;
179         XSendEvent(d, root, False,
180                    SubstructureRedirectMask | SubstructureNotifyMask, &xev);
181
182         return 0;
183 }
184
185 EXPORT_API int x_raise_win(pid_t pid)
186 {
187
188         int r;
189         int found;
190         Display *d;
191         Window win;
192
193         if (pid < 1) {
194                 errno = EINVAL;
195                 return -1;
196         }
197
198         r = kill(pid, 0);
199         if (r == -1) {
200                 errno = ESRCH;  /* No such process */
201                 return -1;
202         }
203
204         d = XOpenDisplay(NULL);
205         _retv_if(d == NULL, -1);
206
207         win = XDefaultRootWindow(d);
208         if (!a_pid)
209                 a_pid = XInternAtom(d, "_NET_WM_PID", True);
210
211         found = __find_win(d, &win, pid);
212         if (!found) {
213                 XCloseDisplay(d);
214                 errno = ENOENT;
215                 return -1;
216         }
217
218         r = __raise_win(d, win);
219
220         XCloseDisplay(d);
221
222         return r;
223 }
224
225 int x_pause_win(pid_t pid)
226 {
227         int r;
228         Display *d;
229         Window win;
230         Eina_List *list_win = NULL;
231
232         if (pid < 1) {
233                 errno = EINVAL;
234                 return -1;
235         }
236
237         r = kill(pid, 0);
238         if (r == -1) {
239                 errno = ESRCH;
240                 return -1;
241         }
242
243         d = XOpenDisplay(NULL);
244         _retv_if(d == NULL, -1);
245
246         win = XDefaultRootWindow(d);
247         if (!a_pid)
248                 a_pid = XInternAtom(d, "_NET_WM_PID", True);
249
250         __foreach_win(&list_win, d, &win, pid);
251         r = __iconify_win(list_win, d);
252
253         XCloseDisplay(d);
254
255         if (list_win)
256                 eina_list_free(list_win);
257
258         return r;
259 }