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);
80 ErrPrint("Create .live.paused: %s\n", strerror(errno));
83 static inline void remove_paused_file(void)
85 if (unlink(PAUSED_FILE) < 0)
86 ErrPrint("Unlink .live.paused: %s\n", strerror(errno));
89 static inline int get_pid(Ecore_X_Window win)
93 unsigned char *in_pid;
96 atom = ecore_x_atom_get("X_CLIENT_PID");
97 if (ecore_x_window_prop_property_get(win, atom, ECORE_X_ATOM_CARDINAL,
98 sizeof(int), &in_pid, &num) == EINA_FALSE) {
99 if (ecore_x_netwm_pid_get(win, &pid) == EINA_FALSE) {
100 ErrPrint("Failed to get PID from a window 0x%X\n", win);
101 return LB_STATUS_ERROR_INVALID;
104 pid = *(int *)in_pid;
107 ErrPrint("Failed to get PID\n");
108 return LB_STATUS_ERROR_INVALID;
114 static Eina_Bool create_cb(void *data, int type, void *event)
116 Ecore_X_Event_Window_Create *info = event;
117 ecore_x_window_client_sniff(info->win);
118 return ECORE_CALLBACK_PASS_ON;
121 static Eina_Bool destroy_cb(void *data, int type, void *event)
123 // Ecore_X_Event_Window_Destroy *info = event;
124 return ECORE_CALLBACK_PASS_ON;
127 HAPI void xmonitor_handle_state_changes(void)
131 struct event_item *item;
133 paused = client_is_all_paused() || setting_is_lcd_off();
134 if (s_info.paused == paused)
137 s_info.paused = paused;
140 EINA_LIST_FOREACH(s_info.pause_list, l, item) {
142 item->cb(item->user_data);
147 sqlite3_release_memory(SQLITE_FLUSH_MAX);
150 remove_paused_file();
152 EINA_LIST_FOREACH(s_info.resume_list, l, item) {
154 item->cb(item->user_data);
159 HAPI int xmonitor_update_state(int target_pid)
162 struct client_node *client;
166 return LB_STATUS_SUCCESS;
168 win = ecore_x_window_focus_get();
172 DbgPrint("Focused window has no PID %X\n", win);
173 client = client_find_by_pid(target_pid);
175 DbgPrint("Client window has no focus now\n");
176 client_paused(client);
178 return LB_STATUS_ERROR_NOT_EXIST;
181 client = client_find_by_pid(pid);
183 DbgPrint("Client %d is not registered yet\n", pid);
184 client = client_find_by_pid(target_pid);
186 DbgPrint("Client window has no focus now\n");
187 client_paused(client);
189 return LB_STATUS_ERROR_INVALID;
192 if (target_pid != pid) {
193 DbgPrint("Client is paused\n");
194 client_paused(client);
196 DbgPrint("Client is resumed\n");
197 client_resumed(client);
200 xmonitor_handle_state_changes();
201 return LB_STATUS_SUCCESS;
204 static Eina_Bool client_cb(void *data, int type, void *event)
206 Ecore_X_Event_Client_Message *info = event;
207 struct client_node *client;
211 pid = get_pid(info->win);
213 return ECORE_CALLBACK_PASS_ON;
215 client = client_find_by_pid(pid);
217 return ECORE_CALLBACK_PASS_ON;
219 name = ecore_x_atom_name_get(info->message_type);
221 return ECORE_CALLBACK_PASS_ON;
223 if (!strcmp(name, "_X_ILLUME_DEACTIVATE_WINDOW")) {
224 DbgPrint("PAUSE EVENT\n");
225 xmonitor_pause(client);
226 } else if (!strcmp(name, "_X_ILLUME_ACTIVATE_WINDOW")) {
227 DbgPrint("RESUME EVENT\n");
228 xmonitor_resume(client);
234 return ECORE_CALLBACK_PASS_ON;
237 static inline void sniff_all_windows(void)
241 struct stack_item *new_item;
242 struct stack_item *item;
243 Eina_List *win_stack;
246 Ecore_X_Window *wins;
251 root = ecore_x_window_root_first_get();
252 ecore_x_window_sniff(root);
254 new_item = malloc(sizeof(*new_item));
256 ErrPrint("Error(%s)\n", strerror(errno));
260 new_item->nr_of_wins = 0;
262 ecore_x_window_children_get(root, &new_item->nr_of_wins);
268 win_stack = eina_list_append(win_stack, new_item);
272 while ((item = eina_list_nth(win_stack, 0))) {
273 win_stack = eina_list_remove(win_stack, item);
280 while (item->i < item->nr_of_wins) {
281 ret = item->wins[item->i];
284 * Now we don't need to care about visibility of window,
285 * just check whether it is registered or not.
286 * (ecore_x_window_visible_get(ret))
288 ecore_x_window_client_sniff(ret);
290 new_item = malloc(sizeof(*new_item));
292 ErrPrint("Error %s\n", strerror(errno));
298 new_item->nr_of_wins = 0;
300 ecore_x_window_children_get(ret,
301 &new_item->nr_of_wins);
302 if (new_item->wins) {
304 eina_list_append(win_stack, new_item);
319 HAPI int xmonitor_pause(struct client_node *client)
321 DbgPrint("%d is paused\n", client_pid(client));
322 client_paused(client);
323 xmonitor_handle_state_changes();
324 return LB_STATUS_SUCCESS;
327 HAPI int xmonitor_resume(struct client_node *client)
329 DbgPrint("%d is resumed\n", client_pid(client));
330 client_resumed(client);
331 xmonitor_handle_state_changes();
332 return LB_STATUS_SUCCESS;
335 static inline void disable_xmonitor(void)
337 ecore_event_handler_del(s_info.create_handler);
338 ecore_event_handler_del(s_info.destroy_handler);
339 ecore_event_handler_del(s_info.client_handler);
341 s_info.create_handler = NULL;
342 s_info.destroy_handler = NULL;
343 s_info.client_handler = NULL;
346 static inline int enable_xmonitor(void)
348 if (ecore_x_composite_query() == EINA_FALSE)
349 DbgPrint("====> COMPOSITOR IS NOT ENABLED\n");
351 s_info.create_handler =
352 ecore_event_handler_add(ECORE_X_EVENT_WINDOW_CREATE,
354 if (!s_info.create_handler) {
355 ErrPrint("Failed to add create event handler\n");
356 return LB_STATUS_ERROR_FAULT;
359 s_info.destroy_handler =
360 ecore_event_handler_add(ECORE_X_EVENT_WINDOW_DESTROY,
362 if (!s_info.create_handler) {
363 ErrPrint("Failed to add destroy event handler\n");
364 ecore_event_handler_del(s_info.create_handler);
365 s_info.create_handler = NULL;
366 return LB_STATUS_ERROR_FAULT;
369 s_info.client_handler =
370 ecore_event_handler_add(ECORE_X_EVENT_CLIENT_MESSAGE,
372 if (!s_info.client_handler) {
373 ErrPrint("Failed to add focus out event handler\n");
374 ecore_event_handler_del(s_info.create_handler);
375 ecore_event_handler_del(s_info.destroy_handler);
376 s_info.create_handler = NULL;
377 s_info.destroy_handler = NULL;
378 return LB_STATUS_ERROR_FAULT;
382 return LB_STATUS_SUCCESS;
385 HAPI int xmonitor_init(void)
389 ret = enable_xmonitor();
394 s_info.paused = client_is_all_paused() || setting_is_lcd_off();
398 remove_paused_file();
400 return LB_STATUS_SUCCESS;
403 HAPI void xmonitor_fini(void)
409 HAPI int xmonitor_add_event_callback(enum xmonitor_event event, int (*cb)(void *user_data), void *user_data)
411 struct event_item *item;
413 item = malloc(sizeof(*item));
415 ErrPrint("Heap: %s\n", strerror(errno));
416 return LB_STATUS_ERROR_MEMORY;
420 item->user_data = user_data;
423 case XMONITOR_PAUSED:
424 s_info.pause_list = eina_list_prepend(s_info.pause_list, item);
426 case XMONITOR_RESUMED:
427 s_info.resume_list = eina_list_prepend(s_info.resume_list, item);
430 ErrPrint("Invalid event type\n");
432 return LB_STATUS_ERROR_INVALID;
435 return LB_STATUS_SUCCESS;
438 HAPI int xmonitor_del_event_callback(enum xmonitor_event event, int (*cb)(void *user_data), void *user_data)
440 struct event_item *item;
445 case XMONITOR_PAUSED:
446 EINA_LIST_FOREACH_SAFE(s_info.pause_list, l, n, item) {
447 if (item->cb == cb && item->user_data == user_data) {
448 s_info.pause_list = eina_list_remove(s_info.pause_list, item);
450 return LB_STATUS_SUCCESS;
455 case XMONITOR_RESUMED:
456 EINA_LIST_FOREACH_SAFE(s_info.resume_list, l, n, item) {
457 if (item->cb == cb && item->user_data == user_data) {
458 s_info.resume_list = eina_list_remove(s_info.resume_list, item);
460 return LB_STATUS_SUCCESS;
465 ErrPrint("Invalid event type\n");
466 return LB_STATUS_ERROR_INVALID;
469 return LB_STATUS_ERROR_NOT_EXIST;
472 HAPI int xmonitor_is_paused(void)
474 return s_info.paused;