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>
35 #include <livebox-errno.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(PAUSED_FILE, 0644);
79 ErrPrint("close: %s\n", strerror(errno));
81 ErrPrint("Create .live.paused: %s\n", strerror(errno));
85 static inline void remove_paused_file(void)
87 if (unlink(PAUSED_FILE) < 0)
88 ErrPrint("Unlink .live.paused: %s\n", strerror(errno));
91 static inline int get_pid(Ecore_X_Window win)
95 unsigned char *in_pid;
98 atom = ecore_x_atom_get("X_CLIENT_PID");
99 if (ecore_x_window_prop_property_get(win, atom, ECORE_X_ATOM_CARDINAL,
100 sizeof(int), &in_pid, &num) == EINA_FALSE) {
101 if (ecore_x_netwm_pid_get(win, &pid) == EINA_FALSE) {
102 ErrPrint("Failed to get PID from a window 0x%X\n", win);
103 return LB_STATUS_ERROR_INVALID;
106 pid = *(int *)in_pid;
109 ErrPrint("Failed to get PID\n");
110 return LB_STATUS_ERROR_INVALID;
116 static Eina_Bool create_cb(void *data, int type, void *event)
118 Ecore_X_Event_Window_Create *info = event;
119 ecore_x_window_client_sniff(info->win);
120 return ECORE_CALLBACK_PASS_ON;
123 static Eina_Bool destroy_cb(void *data, int type, void *event)
125 // Ecore_X_Event_Window_Destroy *info = event;
126 return ECORE_CALLBACK_PASS_ON;
129 HAPI void xmonitor_handle_state_changes(void)
133 struct event_item *item;
135 paused = client_is_all_paused() || setting_is_lcd_off();
136 if (s_info.paused == paused)
139 s_info.paused = paused;
142 EINA_LIST_FOREACH(s_info.pause_list, l, item) {
144 item->cb(item->user_data);
149 sqlite3_release_memory(SQLITE_FLUSH_MAX);
152 remove_paused_file();
154 EINA_LIST_FOREACH(s_info.resume_list, l, item) {
156 item->cb(item->user_data);
161 HAPI int xmonitor_update_state(int target_pid)
164 struct client_node *client;
168 return LB_STATUS_SUCCESS;
170 win = ecore_x_window_focus_get();
174 DbgPrint("Focused window has no PID %X\n", win);
175 client = client_find_by_pid(target_pid);
177 DbgPrint("Client window has no focus now\n");
178 client_paused(client);
180 return LB_STATUS_ERROR_NOT_EXIST;
183 client = client_find_by_pid(pid);
185 DbgPrint("Client %d is not registered yet\n", pid);
186 client = client_find_by_pid(target_pid);
188 DbgPrint("Client window has no focus now\n");
189 client_paused(client);
191 return LB_STATUS_ERROR_INVALID;
194 if (target_pid != pid) {
195 DbgPrint("Client is paused\n");
196 client_paused(client);
198 DbgPrint("Client is resumed\n");
199 client_resumed(client);
202 xmonitor_handle_state_changes();
203 return LB_STATUS_SUCCESS;
206 static Eina_Bool client_cb(void *data, int type, void *event)
208 Ecore_X_Event_Client_Message *info = event;
209 struct client_node *client;
213 pid = get_pid(info->win);
215 return ECORE_CALLBACK_PASS_ON;
217 client = client_find_by_pid(pid);
219 return ECORE_CALLBACK_PASS_ON;
221 name = ecore_x_atom_name_get(info->message_type);
223 return ECORE_CALLBACK_PASS_ON;
225 if (!strcmp(name, "_X_ILLUME_DEACTIVATE_WINDOW")) {
226 DbgPrint("PAUSE EVENT\n");
227 xmonitor_pause(client);
228 } else if (!strcmp(name, "_X_ILLUME_ACTIVATE_WINDOW")) {
229 DbgPrint("RESUME EVENT\n");
230 xmonitor_resume(client);
236 return ECORE_CALLBACK_PASS_ON;
239 static inline void sniff_all_windows(void)
243 struct stack_item *new_item;
244 struct stack_item *item;
245 Eina_List *win_stack;
248 Ecore_X_Window *wins;
253 root = ecore_x_window_root_first_get();
254 ecore_x_window_sniff(root);
256 new_item = malloc(sizeof(*new_item));
258 ErrPrint("Error(%s)\n", strerror(errno));
262 new_item->nr_of_wins = 0;
264 ecore_x_window_children_get(root, &new_item->nr_of_wins);
270 win_stack = eina_list_append(win_stack, new_item);
274 while ((item = eina_list_nth(win_stack, 0))) {
275 win_stack = eina_list_remove(win_stack, item);
282 while (item->i < item->nr_of_wins) {
283 ret = item->wins[item->i];
286 * Now we don't need to care about visibility of window,
287 * just check whether it is registered or not.
288 * (ecore_x_window_visible_get(ret))
290 ecore_x_window_client_sniff(ret);
292 new_item = malloc(sizeof(*new_item));
294 ErrPrint("Error %s\n", strerror(errno));
300 new_item->nr_of_wins = 0;
302 ecore_x_window_children_get(ret,
303 &new_item->nr_of_wins);
304 if (new_item->wins) {
306 eina_list_append(win_stack, new_item);
321 HAPI int xmonitor_pause(struct client_node *client)
323 DbgPrint("%d is paused\n", client_pid(client));
324 client_paused(client);
325 xmonitor_handle_state_changes();
326 return LB_STATUS_SUCCESS;
329 HAPI int xmonitor_resume(struct client_node *client)
331 DbgPrint("%d is resumed\n", client_pid(client));
332 client_resumed(client);
333 xmonitor_handle_state_changes();
334 return LB_STATUS_SUCCESS;
337 static inline void disable_xmonitor(void)
339 ecore_event_handler_del(s_info.create_handler);
340 ecore_event_handler_del(s_info.destroy_handler);
341 ecore_event_handler_del(s_info.client_handler);
343 s_info.create_handler = NULL;
344 s_info.destroy_handler = NULL;
345 s_info.client_handler = NULL;
348 static inline int enable_xmonitor(void)
350 if (ecore_x_composite_query() == EINA_FALSE)
351 DbgPrint("====> COMPOSITOR IS NOT ENABLED\n");
353 s_info.create_handler =
354 ecore_event_handler_add(ECORE_X_EVENT_WINDOW_CREATE,
356 if (!s_info.create_handler) {
357 ErrPrint("Failed to add create event handler\n");
358 return LB_STATUS_ERROR_FAULT;
361 s_info.destroy_handler =
362 ecore_event_handler_add(ECORE_X_EVENT_WINDOW_DESTROY,
364 if (!s_info.create_handler) {
365 ErrPrint("Failed to add destroy event handler\n");
366 ecore_event_handler_del(s_info.create_handler);
367 s_info.create_handler = NULL;
368 return LB_STATUS_ERROR_FAULT;
371 s_info.client_handler =
372 ecore_event_handler_add(ECORE_X_EVENT_CLIENT_MESSAGE,
374 if (!s_info.client_handler) {
375 ErrPrint("Failed to add focus out event handler\n");
376 ecore_event_handler_del(s_info.create_handler);
377 ecore_event_handler_del(s_info.destroy_handler);
378 s_info.create_handler = NULL;
379 s_info.destroy_handler = NULL;
380 return LB_STATUS_ERROR_FAULT;
384 return LB_STATUS_SUCCESS;
387 HAPI int xmonitor_init(void)
391 ret = enable_xmonitor();
396 s_info.paused = client_is_all_paused() || setting_is_lcd_off();
400 remove_paused_file();
402 return LB_STATUS_SUCCESS;
405 HAPI void xmonitor_fini(void)
411 HAPI int xmonitor_add_event_callback(enum xmonitor_event event, int (*cb)(void *user_data), void *user_data)
413 struct event_item *item;
415 item = malloc(sizeof(*item));
417 ErrPrint("Heap: %s\n", strerror(errno));
418 return LB_STATUS_ERROR_MEMORY;
422 item->user_data = user_data;
425 case XMONITOR_PAUSED:
426 s_info.pause_list = eina_list_prepend(s_info.pause_list, item);
428 case XMONITOR_RESUMED:
429 s_info.resume_list = eina_list_prepend(s_info.resume_list, item);
432 ErrPrint("Invalid event type\n");
434 return LB_STATUS_ERROR_INVALID;
437 return LB_STATUS_SUCCESS;
440 HAPI int xmonitor_del_event_callback(enum xmonitor_event event, int (*cb)(void *user_data), void *user_data)
442 struct event_item *item;
447 case XMONITOR_PAUSED:
448 EINA_LIST_FOREACH_SAFE(s_info.pause_list, l, n, item) {
449 if (item->cb == cb && item->user_data == user_data) {
450 s_info.pause_list = eina_list_remove(s_info.pause_list, item);
452 return LB_STATUS_SUCCESS;
457 case XMONITOR_RESUMED:
458 EINA_LIST_FOREACH_SAFE(s_info.resume_list, l, n, item) {
459 if (item->cb == cb && item->user_data == user_data) {
460 s_info.resume_list = eina_list_remove(s_info.resume_list, item);
462 return LB_STATUS_SUCCESS;
467 ErrPrint("Invalid event type\n");
468 return LB_STATUS_ERROR_INVALID;
471 return LB_STATUS_ERROR_NOT_EXIST;
474 HAPI int xmonitor_is_paused(void)
476 return s_info.paused;