021f5650232e96215c2fd145f425398779319684
[platform/upstream/enlightenment.git] / src / bin / e_pointer.c
1 #include "e.h"
2
3 /*
4  * TODO
5  * - Make fallback user controlable.
6  * - Define the allowed signals?
7  */
8
9 typedef struct _E_Pointer_Stack E_Pointer_Stack;
10
11 struct _E_Pointer_Stack
12 {
13    void       *obj;
14    const char *type;
15 };
16
17 static Eina_List *_e_pointers = NULL;
18 static Eina_List *handlers = NULL;
19
20 static void      _e_pointer_canvas_add(E_Pointer *p);
21 static void      _e_pointer_canvas_del(E_Pointer *p);
22 static void      _e_pointer_cb_move(void *data,
23                                     Evas *e __UNUSED__,
24                                     Evas_Object *obj __UNUSED__,
25                                     void *event_info);
26 static void      _e_pointer_free(E_Pointer *p);
27 static void      _e_pointer_stack_free(E_Pointer_Stack *elem);
28 static void      _e_pointer_type_set(E_Pointer *p,
29                                      const char *type);
30 static void      _e_pointer_active_handle(E_Pointer *p);
31
32 static Eina_Bool _e_pointer_cb_mouse_down(void *data,
33                                           int type,
34                                           void *event);
35 static Eina_Bool _e_pointer_cb_mouse_up(void *data,
36                                         int type,
37                                         void *event);
38 static Eina_Bool _e_pointer_cb_mouse_move(void *data,
39                                           int type,
40                                           void *event);
41 static Eina_Bool _e_pointer_cb_mouse_wheel(void *data,
42                                            int type,
43                                            void *event);
44 static Eina_Bool _e_pointer_cb_idle_timer_pre(void *data);
45 static Eina_Bool _e_pointer_cb_idle_timer_wait(void *data);
46 static Eina_Bool _e_pointer_cb_idle_poller(void *data);
47
48 /* externally accessible functions */
49 EINTERN int
50 e_pointer_init(void)
51 {
52    handlers =
53      eina_list_append(handlers,
54                       ecore_event_handler_add(ECORE_EVENT_MOUSE_BUTTON_DOWN,
55                                               _e_pointer_cb_mouse_down, NULL));
56    handlers =
57      eina_list_append(handlers,
58                       ecore_event_handler_add(ECORE_EVENT_MOUSE_BUTTON_UP,
59                                               _e_pointer_cb_mouse_up, NULL));
60    handlers =
61      eina_list_append(handlers,
62                       ecore_event_handler_add(ECORE_EVENT_MOUSE_MOVE,
63                                               _e_pointer_cb_mouse_move, NULL));
64    handlers =
65      eina_list_append(handlers,
66                       ecore_event_handler_add(ECORE_EVENT_MOUSE_WHEEL,
67                                               _e_pointer_cb_mouse_wheel, NULL));
68    return 1;
69 }
70
71 EINTERN int
72 e_pointer_shutdown(void)
73 {
74    E_FREE_LIST(handlers, ecore_event_handler_del);
75    return 1;
76 }
77
78 EAPI E_Pointer *
79 e_pointer_window_new(Ecore_X_Window win,
80                      int filled)
81 {
82    E_Pointer *p = NULL;
83
84    p = E_OBJECT_ALLOC(E_Pointer, E_POINTER_TYPE, _e_pointer_free);
85    if (!p) return NULL;
86
87    p->e_cursor = e_config->use_e_cursor;
88    p->win = win;
89    p->color = 0;
90    if (e_config->use_e_cursor)
91      if (ecore_x_cursor_color_supported_get()) p->color = 1;
92
93    ecore_x_cursor_size_set(e_config->cursor_size * 3 / 4);
94    if (filled) e_pointer_type_push(p, p, "default");
95    _e_pointers = eina_list_append(_e_pointers, p);
96    return p;
97 }
98
99 EAPI void
100 e_pointers_size_set(int size)
101 {
102    Eina_List *l;
103    E_Pointer *p;
104
105    if (!e_config->show_cursor) return;
106    EINA_LIST_FOREACH(_e_pointers, l, p)
107      {
108         Evas_Engine_Info_Buffer *einfo;
109
110         if (p->evas)
111           {
112              p->w = p->h = size;
113              evas_output_size_set(p->evas, p->w, p->h);
114              evas_output_viewport_set(p->evas, 0, 0, p->w, p->h);
115
116              p->pixels = realloc(p->pixels, p->w * p->h * sizeof(int));
117
118              einfo = (Evas_Engine_Info_Buffer *)evas_engine_info_get(p->evas);
119              if (einfo)
120                {
121                   einfo->info.dest_buffer = p->pixels;
122                   einfo->info.dest_buffer_row_bytes = p->w * sizeof(int);
123                   evas_engine_info_set(p->evas, (Evas_Engine_Info *)einfo);
124                }
125
126              evas_object_move(p->pointer_object, 0, 0);
127              evas_object_resize(p->pointer_object, p->w, p->h);
128           }
129         else
130           {
131              const char *type;
132
133              ecore_x_cursor_size_set(e_config->cursor_size * 3 / 4);
134              type = p->type;
135              if (type)
136                {
137                   p->type = NULL;
138                   _e_pointer_type_set(p, type);
139                   eina_stringshare_del(type);
140                }
141           }
142      }
143 }
144
145 EAPI void
146 e_pointer_hide(E_Pointer *p)
147 {
148    if (!p) return;
149    if (p->win) ecore_x_window_cursor_set(p->win, 0);
150    if (p->evas) _e_pointer_canvas_del(p);
151 }
152
153 EAPI void
154 e_pointer_type_push(E_Pointer *p,
155                     void *obj,
156                     const char *type)
157 {
158    E_Pointer_Stack *stack;
159
160    if (!p) return;
161    p->e_cursor = e_config->use_e_cursor;
162
163    _e_pointer_type_set(p, type);
164
165    p->obj = obj;
166
167    stack = E_NEW(E_Pointer_Stack, 1);
168    if (stack)
169      {
170         stack->type = eina_stringshare_add(p->type);
171         stack->obj = p->obj;
172         p->stack = eina_list_prepend(p->stack, stack);
173      }
174 }
175
176 EAPI void
177 e_pointer_type_pop(E_Pointer *p,
178                    void *obj,
179                    const char *type)
180 {
181    Eina_List *l, *l_next;
182    E_Pointer_Stack *stack;
183
184    if (!p) return;
185    EINA_LIST_FOREACH_SAFE(p->stack, l, l_next, stack)
186      {
187         if ((stack->obj == obj) && ((!type) || (!strcmp(stack->type, type))))
188           {
189              _e_pointer_stack_free(stack);
190              p->stack = eina_list_remove_list(p->stack, l);
191              if (type) break;
192           }
193      }
194
195    if (!p->stack)
196      {
197         if (p->evas) _e_pointer_canvas_del(p);
198         ecore_x_window_cursor_set(p->win, 0);
199         if (p->type) eina_stringshare_del(p->type);
200         p->type = NULL;
201         return;
202      }
203
204    stack = eina_list_data_get(p->stack);
205    _e_pointer_type_set(p, stack->type);
206
207    if (p->type) eina_stringshare_del(p->type);
208    p->type = eina_stringshare_add(stack->type);
209    p->obj = stack->obj;
210
211    /* try the default cursor next time */
212    p->e_cursor = e_config->use_e_cursor;
213 }
214
215 EAPI void
216 e_pointer_idler_before(void)
217 {
218    Eina_List *l;
219    E_Pointer *p;
220
221    if (!e_config->show_cursor) return;
222    EINA_LIST_FOREACH(_e_pointers, l, p)
223      {
224         Eina_List *updates;
225
226         if (!p->e_cursor) continue;
227         if (!p->evas) continue;
228
229         updates = evas_render_updates(p->evas);
230         if ((updates) || (p->hot.update))
231           {
232              Ecore_X_Cursor cur;
233
234              cur = ecore_x_cursor_new(p->win, p->pixels, p->w, p->h,
235                                       p->hot.x, p->hot.y);
236              ecore_x_window_cursor_set(p->win, cur);
237              ecore_x_cursor_free(cur);
238              evas_render_updates_free(updates);
239              p->hot.update = 0;
240           }
241      }
242 }
243
244 /**
245  * mode_{push,pop} functions are ONLY for use with compositor objects.
246  * these functions should NEVER be used for setting internal window pointers!!!!
247  */
248 EAPI void
249 e_pointer_mode_push(void *obj, E_Pointer_Mode mode)
250 {
251    switch (mode)
252      {
253       case E_POINTER_RESIZE_TL:
254         e_pointer_type_push(e_comp_get(obj)->pointer, obj, "resize_tl");
255         break;
256
257       case E_POINTER_RESIZE_T:
258         e_pointer_type_push(e_comp_get(obj)->pointer, obj, "resize_t");
259         break;
260
261       case E_POINTER_RESIZE_TR:
262         e_pointer_type_push(e_comp_get(obj)->pointer, obj, "resize_tr");
263         break;
264
265       case E_POINTER_RESIZE_R:
266         e_pointer_type_push(e_comp_get(obj)->pointer, obj, "resize_r");
267         break;
268
269       case E_POINTER_RESIZE_BR:
270         e_pointer_type_push(e_comp_get(obj)->pointer, obj, "resize_br");
271         break;
272
273       case E_POINTER_RESIZE_B:
274         e_pointer_type_push(e_comp_get(obj)->pointer, obj, "resize_b");
275         break;
276
277       case E_POINTER_RESIZE_BL:
278         e_pointer_type_push(e_comp_get(obj)->pointer, obj, "resize_bl");
279         break;
280
281       case E_POINTER_RESIZE_L:
282         e_pointer_type_push(e_comp_get(obj)->pointer, obj, "resize_l");
283         break;
284
285       case E_POINTER_MOVE:
286         e_pointer_type_push(e_comp_get(obj)->pointer, obj, "move");
287         break;
288
289       default: break;
290      }
291 }
292
293 EAPI void
294 e_pointer_mode_pop(void *obj, E_Pointer_Mode mode)
295 {
296    switch (mode)
297      {
298       case E_POINTER_RESIZE_TL:
299         e_pointer_type_pop(e_comp_get(obj)->pointer, obj, "resize_tl");
300         break;
301
302       case E_POINTER_RESIZE_T:
303         e_pointer_type_pop(e_comp_get(obj)->pointer, obj, "resize_t");
304         break;
305
306       case E_POINTER_RESIZE_TR:
307         e_pointer_type_pop(e_comp_get(obj)->pointer, obj, "resize_tr");
308         break;
309
310       case E_POINTER_RESIZE_R:
311         e_pointer_type_pop(e_comp_get(obj)->pointer, obj, "resize_r");
312         break;
313
314       case E_POINTER_RESIZE_BR:
315         e_pointer_type_pop(e_comp_get(obj)->pointer, obj, "resize_br");
316         break;
317
318       case E_POINTER_RESIZE_B:
319         e_pointer_type_pop(e_comp_get(obj)->pointer, obj, "resize_b");
320         break;
321
322       case E_POINTER_RESIZE_BL:
323         e_pointer_type_pop(e_comp_get(obj)->pointer, obj, "resize_bl");
324         break;
325
326       case E_POINTER_RESIZE_L:
327         e_pointer_type_pop(e_comp_get(obj)->pointer, obj, "resize_l");
328         break;
329
330       case E_POINTER_MOVE:
331         e_pointer_type_pop(e_comp_get(obj)->pointer, obj, "move");
332         break;
333
334       default: break;
335      }
336 }
337
338 /* local subsystem functions */
339 static void
340 _e_pointer_canvas_add(E_Pointer *p)
341 {
342    Evas_Engine_Info_Buffer *einfo;
343    Evas_Object *o;
344    int rmethod;
345
346    if (!p) return;
347    p->w = e_config->cursor_size;
348    p->h = e_config->cursor_size;
349
350    /* create evas */
351    p->evas = evas_new();
352    if (!p->evas)
353      {
354         e_object_del(E_OBJECT(p));
355         return;
356      }
357    rmethod = evas_render_method_lookup("buffer");
358    evas_output_method_set(p->evas, rmethod);
359    evas_output_size_set(p->evas, p->w, p->h);
360    evas_output_viewport_set(p->evas, 0, 0, p->w, p->h);
361
362    p->pixels = malloc(p->w * p->h * sizeof(int));
363    if (!p->pixels)
364      {
365         _e_pointer_canvas_del(p);
366         return;
367      }
368    einfo = (Evas_Engine_Info_Buffer *)evas_engine_info_get(p->evas);
369    if (!einfo)
370      {
371         _e_pointer_canvas_del(p);
372         return;
373      }
374    einfo->info.depth_type = EVAS_ENGINE_BUFFER_DEPTH_ARGB32;
375    einfo->info.dest_buffer = p->pixels;
376    einfo->info.dest_buffer_row_bytes = p->w * sizeof(int);
377    einfo->info.use_color_key = 0;
378    einfo->info.alpha_threshold = 0;
379    einfo->info.func.new_update_region = NULL;
380    einfo->info.func.free_update_region = NULL;
381    evas_engine_info_set(p->evas, (Evas_Engine_Info *)einfo);
382
383    /* set the pointer edje */
384    o = edje_object_add(p->evas);
385    p->pointer_object = o;
386    /* Create the hotspot object */
387    o = evas_object_rectangle_add(p->evas);
388    evas_object_color_set(o, 0, 0, 0, 0);
389    p->hot_object = o;
390    evas_object_event_callback_add(o, EVAS_CALLBACK_MOVE,
391                                   _e_pointer_cb_move, p);
392    /* init edje */
393    evas_object_move(p->pointer_object, 0, 0);
394    evas_object_resize(p->pointer_object, p->w, p->h);
395    evas_object_show(p->pointer_object);
396 }
397
398 static void
399 _e_pointer_canvas_del(E_Pointer *p)
400 {
401    if (!p) return;
402    if (p->pointer_object) evas_object_del(p->pointer_object);
403    if (p->hot_object) evas_object_del(p->hot_object);
404    if (p->evas) evas_free(p->evas);
405    free(p->pixels);
406    p->pointer_object = NULL;
407    p->hot_object = NULL;
408    p->evas = NULL;
409    p->pixels = NULL;
410 }
411
412 static void
413 _e_pointer_cb_move(void *data,
414                    Evas *e __UNUSED__,
415                    Evas_Object *obj __UNUSED__,
416                    void *event_info __UNUSED__)
417 {
418    E_Pointer *p;
419    Evas_Coord x, y;
420
421    if (!e_config->show_cursor) return;
422
423    if (!(p = data)) return;
424    if (!p->e_cursor) return;
425    edje_object_part_geometry_get(p->pointer_object, "e.swallow.hotspot",
426                                  &x, &y, NULL, NULL);
427    if ((p->hot.x != x) || (p->hot.y != y))
428      {
429         p->hot.x = x;
430         p->hot.y = y;
431         p->hot.update = 1;
432      }
433 }
434
435 static void
436 _e_pointer_free(E_Pointer *p)
437 {
438    if (!p) return;
439    _e_pointers = eina_list_remove(_e_pointers, p);
440
441    _e_pointer_canvas_del(p);
442
443    E_FREE_LIST(p->stack, _e_pointer_stack_free);
444
445    if (p->type) eina_stringshare_del(p->type);
446    if (p->idle_timer) ecore_timer_del(p->idle_timer);
447    if (p->idle_poller) ecore_poller_del(p->idle_poller);
448
449    p->type = NULL;
450    p->idle_timer = NULL;
451    p->idle_poller = NULL;
452    E_FREE(p);
453 }
454
455 static void
456 _e_pointer_stack_free(E_Pointer_Stack *elem)
457 {
458    if (elem->type) eina_stringshare_del(elem->type);
459    free(elem);
460 }
461
462 static void
463 _e_pointer_type_set(E_Pointer *p,
464                     const char *type)
465 {
466    if (!p) return;
467
468    /* Check if this pointer is already set */
469    if ((p->type) && (!strcmp(p->type, type))) return;
470
471    eina_stringshare_replace(&p->type, type);
472
473    /* Do not set type if in "hidden mode" */
474    if (!e_config->show_cursor)
475      {
476         ecore_x_window_cursor_set(p->win, 0);
477         return;
478      }
479
480    if (p->e_cursor)
481      {
482         char cursor[1024];
483         Evas_Coord x, y;
484
485         if (!p->evas) _e_pointer_canvas_add(p);
486         if (p->color)
487           snprintf(cursor, sizeof(cursor),
488                    "e/pointer/enlightenment/%s/color", type);
489         else
490           snprintf(cursor, sizeof(cursor),
491                    "e/pointer/enlightenment/%s/mono", type);
492         if (!e_theme_edje_object_set(p->pointer_object,
493                                      "base/theme/pointer", cursor))
494           goto fallback;
495         edje_object_part_swallow(p->pointer_object, "e.swallow.hotspot",
496                                  p->hot_object);
497         edje_object_part_geometry_get(p->pointer_object, "e.swallow.hotspot",
498                                       &x, &y, NULL, NULL);
499         if ((p->hot.x != x) || (p->hot.y != y))
500           {
501              p->hot.x = x;
502              p->hot.y = y;
503           }
504         p->hot.update = 1;
505         return;
506      }
507 fallback:
508    {
509       Ecore_X_Cursor cursor = 0;
510
511       if (p->evas) _e_pointer_canvas_del(p);
512       if (!strcmp(type, "move"))
513         cursor = ecore_x_cursor_shape_get(ECORE_X_CURSOR_FLEUR);
514 #if 0
515       else if (!strcmp(type, "resize"))
516         cursor = ecore_x_cursor_shape_get(ECORE_X_CURSOR_SIZING);
517 #endif
518       else if (!strcmp(type, "resize_tl"))
519         cursor = ecore_x_cursor_shape_get(ECORE_X_CURSOR_TOP_LEFT_CORNER);
520       else if (!strcmp(type, "resize_t"))
521         cursor = ecore_x_cursor_shape_get(ECORE_X_CURSOR_TOP_SIDE);
522       else if (!strcmp(type, "resize_tr"))
523         cursor = ecore_x_cursor_shape_get(ECORE_X_CURSOR_TOP_RIGHT_CORNER);
524       else if (!strcmp(type, "resize_r"))
525         cursor = ecore_x_cursor_shape_get(ECORE_X_CURSOR_RIGHT_SIDE);
526       else if (!strcmp(type, "resize_br"))
527         cursor = ecore_x_cursor_shape_get(ECORE_X_CURSOR_BOTTOM_RIGHT_CORNER);
528       else if (!strcmp(type, "resize_b"))
529         cursor = ecore_x_cursor_shape_get(ECORE_X_CURSOR_BOTTOM_SIDE);
530       else if (!strcmp(type, "resize_bl"))
531         cursor = ecore_x_cursor_shape_get(ECORE_X_CURSOR_BOTTOM_LEFT_CORNER);
532       else if (!strcmp(type, "resize_l"))
533         cursor = ecore_x_cursor_shape_get(ECORE_X_CURSOR_LEFT_SIDE);
534       else if (!strcmp(type, "entry"))
535         cursor = ecore_x_cursor_shape_get(ECORE_X_CURSOR_XTERM);
536       else if (!strcmp(type, "default"))
537         cursor = ecore_x_cursor_shape_get(ECORE_X_CURSOR_LEFT_PTR);
538       else if (!strcmp(type, "plus"))
539         cursor = ecore_x_cursor_shape_get(ECORE_X_CURSOR_PLUS);
540       else if (!strcmp(type, "hand"))
541         cursor = ecore_x_cursor_shape_get(ECORE_X_CURSOR_HAND1);
542       else if (!strcmp(type, "rotate"))
543         cursor = ecore_x_cursor_shape_get(ECORE_X_CURSOR_EXCHANGE);
544       else
545         {
546            printf("Unknown pointer type: %s\n", type);
547            cursor = ecore_x_cursor_shape_get(ECORE_X_CURSOR_ARROW);
548         }
549       if (!cursor) printf("X Cursor for %s is missing\n", type);
550       ecore_x_window_cursor_set(p->win, cursor);
551       if (cursor) ecore_x_cursor_free(cursor);
552    }
553 }
554
555 static void
556 _e_pointer_active_handle(E_Pointer *p)
557 {
558    if (!p) return;
559
560    /* we got some mouse event - if there was an idle timer emit an active
561     * signal as we WERE idle, NOW we are active */
562    if (p->idle_timer)
563      {
564         ecore_timer_del(p->idle_timer);
565         p->idle_timer = NULL;
566      }
567    if (p->idle_poller)
568      {
569         ecore_poller_del(p->idle_poller);
570         p->idle_poller = NULL;
571      }
572    if (p->idle)
573      {
574         if (p->pointer_object)
575           edje_object_signal_emit(p->pointer_object, "e,state,mouse,active", "e");
576         p->idle = 0;
577      }
578    if (e_powersave_mode_get() >= E_POWERSAVE_MODE_MEDIUM) return;
579    /* and schedule a pre-idle check in 1 second if no more events happen */
580    if (!e_config->idle_cursor) return;
581    p->idle_timer = ecore_timer_loop_add(1.0, _e_pointer_cb_idle_timer_pre, p);
582 }
583
584 static Eina_Bool
585 _e_pointer_cb_mouse_down(void *data __UNUSED__,
586                          int type __UNUSED__,
587                          void *event __UNUSED__)
588 {
589    Eina_List *l;
590    E_Pointer *p;
591
592    EINA_LIST_FOREACH(_e_pointers, l, p)
593      {
594         _e_pointer_active_handle(p);
595         if (e_powersave_mode_get() < E_POWERSAVE_MODE_EXTREME)
596           {
597              if (p->pointer_object)
598                edje_object_signal_emit(p->pointer_object,
599                                        "e,action,mouse,down", "e");
600           }
601      }
602    return ECORE_CALLBACK_PASS_ON;
603 }
604
605 static Eina_Bool
606 _e_pointer_cb_mouse_up(void *data __UNUSED__,
607                        int type __UNUSED__,
608                        void *event __UNUSED__)
609 {
610    Eina_List *l;
611    E_Pointer *p;
612
613    EINA_LIST_FOREACH(_e_pointers, l, p)
614      {
615         _e_pointer_active_handle(p);
616         if (e_powersave_mode_get() < E_POWERSAVE_MODE_EXTREME)
617           {
618              if (p->pointer_object)
619                edje_object_signal_emit(p->pointer_object,
620                                        "e,action,mouse,up", "e");
621           }
622      }
623    return ECORE_CALLBACK_PASS_ON;
624 }
625
626 static Eina_Bool
627 _e_pointer_cb_mouse_move(void *data __UNUSED__,
628                          int type __UNUSED__,
629                          void *event __UNUSED__)
630 {
631    Eina_List *l;
632    E_Pointer *p;
633
634    EINA_LIST_FOREACH(_e_pointers, l, p)
635      {
636         _e_pointer_active_handle(p);
637         if (e_powersave_mode_get() < E_POWERSAVE_MODE_HIGH)
638           {
639              if (p->pointer_object)
640                edje_object_signal_emit(p->pointer_object,
641                                        "e,action,mouse,move", "e");
642           }
643      }
644    return ECORE_CALLBACK_PASS_ON;
645 }
646
647 static Eina_Bool
648 _e_pointer_cb_mouse_wheel(void *data __UNUSED__,
649                           int type __UNUSED__,
650                           void *event __UNUSED__)
651 {
652    Eina_List *l;
653    E_Pointer *p;
654
655    EINA_LIST_FOREACH(_e_pointers, l, p)
656      {
657         _e_pointer_active_handle(p);
658         if (e_powersave_mode_get() < E_POWERSAVE_MODE_EXTREME)
659           {
660              if (p->pointer_object)
661                edje_object_signal_emit(p->pointer_object,
662                                        "e,action,mouse,wheel", "e");
663           }
664      }
665    return ECORE_CALLBACK_PASS_ON;
666 }
667
668 static Eina_Bool
669 _e_pointer_cb_idle_timer_pre(void *data)
670 {
671    E_Pointer *p;
672    int x, y;
673
674    if (!(p = data)) return ECORE_CALLBACK_RENEW;
675    ecore_x_pointer_xy_get(p->win, &x, &y);
676    p->x = x;
677    p->y = y;
678    p->idle_timer = ecore_timer_loop_add(4.0, _e_pointer_cb_idle_timer_wait, p);
679    return ECORE_CALLBACK_CANCEL;
680 }
681
682 static Eina_Bool
683 _e_pointer_cb_idle_timer_wait(void *data)
684 {
685    E_Pointer *p;
686
687    if (!(p = data)) return ECORE_CALLBACK_RENEW;
688    if ((e_powersave_mode_get() >= E_POWERSAVE_MODE_MEDIUM) ||
689        (!e_config->idle_cursor))
690      {
691         if (p->idle_poller) ecore_poller_del(p->idle_poller);
692         p->idle_poller = NULL;
693         p->idle_timer = NULL;
694         return ECORE_CALLBACK_CANCEL;
695      }
696    if (!p->idle_poller)
697      p->idle_poller = ecore_poller_add(ECORE_POLLER_CORE, 64,
698                                        _e_pointer_cb_idle_poller, p);
699    p->idle_timer = NULL;
700    return ECORE_CALLBACK_CANCEL;
701 }
702
703 static Eina_Bool
704 _e_pointer_cb_idle_poller(void *data)
705 {
706    E_Pointer *p;
707    int x, y;
708
709    if (!(p = data)) return ECORE_CALLBACK_RENEW;
710    if ((e_powersave_mode_get() >= E_POWERSAVE_MODE_MEDIUM) ||
711        (!e_config->idle_cursor))
712      {
713         p->idle_poller = NULL;
714         return ECORE_CALLBACK_CANCEL;
715      }
716    /* check if pointer actually moved since the 1 second post-mouse move idle
717     * pre-timer that fetches the position */
718    ecore_x_pointer_xy_get(p->win, &x, &y);
719    if ((x != p->x) || (y != p->y))
720      {
721         /* it moved - so we are not idle yet - record position and wait
722          * 4 secons more */
723         p->x = x;
724         p->y = y;
725         if (p->idle)
726           {
727              if (p->pointer_object)
728                edje_object_signal_emit(p->pointer_object,
729                                        "e,state,mouse,active", "e");
730              p->idle = 0;
731           }
732         /* use poller to check from now on */
733         return ECORE_CALLBACK_RENEW;
734      }
735    /* we are idle - report it if not idle before */
736    if (!p->idle)
737      {
738         if (p->pointer_object)
739           edje_object_signal_emit(p->pointer_object, "e,state,mouse,idle", "e");
740         p->idle = 1;
741      }
742    return ECORE_CALLBACK_RENEW;
743 }
744