2 * Copyright 2013 Samsung Electronics Co., Ltd
4 * Licensed under the Flora License, Version 1.1 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://floralicense.org/license/
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
25 #include <sys/types.h>
34 #include <dynamicbox_errno.h>
35 #include <dynamicbox_conf.h>
39 #include "client_life.h"
40 #include "slave_life.h"
49 int (*cb)(void *user_data);
54 Ecore_Event_Handler *create_handler;
55 Ecore_Event_Handler *destroy_handler;
56 Ecore_Event_Handler *client_handler;
58 Eina_List *pause_list;
59 Eina_List *resume_list;
63 .create_handler = NULL,
64 .destroy_handler = NULL,
65 .client_handler = NULL,
70 .paused = 1, /*!< The provider is treated as paused process when it is launched */
73 static inline void touch_paused_file(void)
76 fd = creat(DYNAMICBOX_CONF_PAUSED_FILE, 0644);
79 ErrPrint("close: %s\n", strerror(errno));
82 ErrPrint("Create .live.paused: %s\n", strerror(errno));
86 static inline void remove_paused_file(void)
88 if (unlink(DYNAMICBOX_CONF_PAUSED_FILE) < 0) {
89 ErrPrint("Unlink .live.paused: %s\n", strerror(errno));
93 static inline int get_pid(Ecore_X_Window win)
97 unsigned char *in_pid;
100 atom = ecore_x_atom_get("X_CLIENT_PID");
101 if (ecore_x_window_prop_property_get(win, atom, ECORE_X_ATOM_CARDINAL,
102 sizeof(int), &in_pid, &num) == EINA_FALSE) {
103 if (ecore_x_netwm_pid_get(win, &pid) == EINA_FALSE) {
104 ErrPrint("Failed to get PID from a window 0x%X\n", win);
105 return DBOX_STATUS_ERROR_INVALID_PARAMETER;
108 pid = *(int *)in_pid;
111 ErrPrint("Failed to get PID\n");
112 return DBOX_STATUS_ERROR_INVALID_PARAMETER;
118 static Eina_Bool create_cb(void *data, int type, void *event)
120 Ecore_X_Event_Window_Create *info = event;
121 ecore_x_window_client_sniff(info->win);
122 return ECORE_CALLBACK_PASS_ON;
125 static Eina_Bool destroy_cb(void *data, int type, void *event)
127 // Ecore_X_Event_Window_Destroy *info = event;
128 return ECORE_CALLBACK_PASS_ON;
131 HAPI void xmonitor_handle_state_changes(void)
135 struct event_item *item;
137 paused = client_is_all_paused() || setting_is_lcd_off();
138 if (s_info.paused == paused) {
142 s_info.paused = paused;
145 EINA_LIST_FOREACH(s_info.pause_list, l, item) {
147 item->cb(item->user_data);
153 sqlite3_release_memory(DYNAMICBOX_CONF_SQLITE_FLUSH_MAX);
156 remove_paused_file();
158 EINA_LIST_FOREACH(s_info.resume_list, l, item) {
160 item->cb(item->user_data);
166 HAPI int xmonitor_update_state(int target_pid)
169 struct client_node *client;
172 if (!DYNAMICBOX_CONF_USE_XMONITOR || target_pid < 0) {
173 return DBOX_STATUS_ERROR_NONE;
176 win = ecore_x_window_focus_get();
180 DbgPrint("Focused window has no PID %X\n", win);
181 client = client_find_by_pid(target_pid);
183 DbgPrint("Client window has no focus now\n");
184 client_paused(client);
186 return DBOX_STATUS_ERROR_NOT_EXIST;
189 client = client_find_by_pid(pid);
191 DbgPrint("Client %d is not registered yet\n", pid);
192 client = client_find_by_pid(target_pid);
194 DbgPrint("Client window has no focus now\n");
195 client_paused(client);
197 return DBOX_STATUS_ERROR_INVALID_PARAMETER;
200 if (target_pid != pid) {
201 DbgPrint("Client is paused\n");
202 client_paused(client);
204 DbgPrint("Client is resumed\n");
205 client_resumed(client);
208 xmonitor_handle_state_changes();
209 return DBOX_STATUS_ERROR_NONE;
212 static Eina_Bool client_cb(void *data, int type, void *event)
214 Ecore_X_Event_Client_Message *info = event;
215 struct client_node *client;
219 pid = get_pid(info->win);
221 return ECORE_CALLBACK_PASS_ON;
224 client = client_find_by_pid(pid);
226 return ECORE_CALLBACK_PASS_ON;
229 name = ecore_x_atom_name_get(info->message_type);
231 return ECORE_CALLBACK_PASS_ON;
234 if (!strcmp(name, "_X_ILLUME_DEACTIVATE_WINDOW")) {
235 xmonitor_pause(client);
236 } else if (!strcmp(name, "_X_ILLUME_ACTIVATE_WINDOW")) {
237 xmonitor_resume(client);
243 return ECORE_CALLBACK_PASS_ON;
246 static inline void sniff_all_windows(void)
250 struct stack_item *new_item;
251 struct stack_item *item;
252 Eina_List *win_stack;
255 Ecore_X_Window *wins;
260 root = ecore_x_window_root_first_get();
261 ecore_x_window_sniff(root);
263 new_item = malloc(sizeof(*new_item));
265 ErrPrint("Error(%s)\n", strerror(errno));
269 new_item->nr_of_wins = 0;
271 ecore_x_window_children_get(root, &new_item->nr_of_wins);
276 if (new_item->wins) {
277 win_stack = eina_list_append(win_stack, new_item);
282 while ((item = eina_list_nth(win_stack, 0))) {
283 win_stack = eina_list_remove(win_stack, item);
290 while (item->i < item->nr_of_wins) {
291 ret = item->wins[item->i];
294 * Now we don't need to care about visibility of window,
295 * just check whether it is registered or not.
296 * (ecore_x_window_visible_get(ret))
298 ecore_x_window_client_sniff(ret);
300 new_item = malloc(sizeof(*new_item));
302 ErrPrint("Error %s\n", strerror(errno));
308 new_item->nr_of_wins = 0;
310 ecore_x_window_children_get(ret,
311 &new_item->nr_of_wins);
312 if (new_item->wins) {
314 eina_list_append(win_stack, new_item);
329 HAPI int xmonitor_pause(struct client_node *client)
331 DbgPrint("%d is paused\n", client_pid(client));
332 client_paused(client);
333 xmonitor_handle_state_changes();
334 return DBOX_STATUS_ERROR_NONE;
337 HAPI int xmonitor_resume(struct client_node *client)
339 DbgPrint("%d is resumed\n", client_pid(client));
340 client_resumed(client);
341 xmonitor_handle_state_changes();
342 return DBOX_STATUS_ERROR_NONE;
345 static inline void disable_xmonitor(void)
347 ecore_event_handler_del(s_info.create_handler);
348 ecore_event_handler_del(s_info.destroy_handler);
349 ecore_event_handler_del(s_info.client_handler);
351 s_info.create_handler = NULL;
352 s_info.destroy_handler = NULL;
353 s_info.client_handler = NULL;
356 static inline int enable_xmonitor(void)
358 if (ecore_x_composite_query() == EINA_FALSE) {
359 DbgPrint("====> COMPOSITOR IS NOT ENABLED\n");
362 s_info.create_handler =
363 ecore_event_handler_add(ECORE_X_EVENT_WINDOW_CREATE,
365 if (!s_info.create_handler) {
366 ErrPrint("Failed to add create event handler\n");
367 return DBOX_STATUS_ERROR_FAULT;
370 s_info.destroy_handler =
371 ecore_event_handler_add(ECORE_X_EVENT_WINDOW_DESTROY,
373 if (!s_info.destroy_handler) {
374 ErrPrint("Failed to add destroy event handler\n");
375 ecore_event_handler_del(s_info.create_handler);
376 s_info.create_handler = NULL;
377 return DBOX_STATUS_ERROR_FAULT;
380 s_info.client_handler =
381 ecore_event_handler_add(ECORE_X_EVENT_CLIENT_MESSAGE,
383 if (!s_info.client_handler) {
384 ErrPrint("Failed to add focus out event handler\n");
385 ecore_event_handler_del(s_info.create_handler);
386 ecore_event_handler_del(s_info.destroy_handler);
387 s_info.create_handler = NULL;
388 s_info.destroy_handler = NULL;
389 return DBOX_STATUS_ERROR_FAULT;
393 return DBOX_STATUS_ERROR_NONE;
396 HAPI int xmonitor_init(void)
398 if (DYNAMICBOX_CONF_USE_XMONITOR) {
400 ret = enable_xmonitor();
406 s_info.paused = client_is_all_paused() || setting_is_lcd_off();
410 remove_paused_file();
413 return DBOX_STATUS_ERROR_NONE;
416 HAPI void xmonitor_fini(void)
418 if (DYNAMICBOX_CONF_USE_XMONITOR) {
423 HAPI int xmonitor_add_event_callback(enum xmonitor_event event, int (*cb)(void *user_data), void *user_data)
425 struct event_item *item;
427 item = malloc(sizeof(*item));
429 ErrPrint("Heap: %s\n", strerror(errno));
430 return DBOX_STATUS_ERROR_OUT_OF_MEMORY;
434 item->user_data = user_data;
437 case XMONITOR_PAUSED:
438 s_info.pause_list = eina_list_prepend(s_info.pause_list, item);
440 case XMONITOR_RESUMED:
441 s_info.resume_list = eina_list_prepend(s_info.resume_list, item);
444 ErrPrint("Invalid event type\n");
446 return DBOX_STATUS_ERROR_INVALID_PARAMETER;
449 return DBOX_STATUS_ERROR_NONE;
452 HAPI int xmonitor_del_event_callback(enum xmonitor_event event, int (*cb)(void *user_data), void *user_data)
454 struct event_item *item;
459 case XMONITOR_PAUSED:
460 EINA_LIST_FOREACH_SAFE(s_info.pause_list, l, n, item) {
461 if (item->cb == cb && item->user_data == user_data) {
462 s_info.pause_list = eina_list_remove(s_info.pause_list, item);
464 return DBOX_STATUS_ERROR_NONE;
469 case XMONITOR_RESUMED:
470 EINA_LIST_FOREACH_SAFE(s_info.resume_list, l, n, item) {
471 if (item->cb == cb && item->user_data == user_data) {
472 s_info.resume_list = eina_list_remove(s_info.resume_list, item);
474 return DBOX_STATUS_ERROR_NONE;
479 ErrPrint("Invalid event type\n");
480 return DBOX_STATUS_ERROR_INVALID_PARAMETER;
483 return DBOX_STATUS_ERROR_NOT_EXIST;
486 HAPI int xmonitor_is_paused(void)
488 return s_info.paused;