1 #include "e_mod_effect_rotation.h"
3 #include <tbm_bufmgr.h>
4 #include <tbm_surface.h>
5 #include <tbm_surface_internal.h>
6 #include <tdm_helper.h>
7 #include <wayland-tbm-server.h>
10 #define e_util_size_debug_set(x, y)
13 typedef struct _Rotation_Effect_Object
18 struct wl_shm_pool *data_pool;
20 } Rotation_Effect_Object;
22 typedef struct _Rotation_Effect_Begin_Context
29 } Rotation_Effect_Begin_Context;
31 typedef struct _Rotation_Effect_End_Context
38 } Rotation_Effect_End_Context;
40 typedef struct _Rotation_Effect
46 Eina_List *waiting_list;
48 Rotation_Effect_Begin_Context *ctx_begin;
49 Rotation_Effect_End_Context *ctx_end;
51 Ecore_Animator *animator;
54 Eina_Bool wait_for_buffer;
56 Ecore_Timer *norender_timer;
59 typedef struct _Rotation_Zone
62 Eina_List *event_hdlrs;
64 Rotation_Effect *effect;
70 static Rotation_Zone *_rotation_zone = NULL;
73 _rotation_effect_event_free(void *data EINA_UNUSED, void *event)
79 _rotation_effect_ready_send(E_Zone *zone)
81 E_Event_Zone_Rotation_Effect_Ready *ev;
83 ev = E_NEW(E_Event_Zone_Rotation_Effect_Ready, 1);
87 ecore_event_add(E_EVENT_ZONE_ROTATION_EFFECT_READY, ev, _rotation_effect_event_free, NULL);
89 EFFINF("Rotation Effect Event Ready", NULL);
93 _rotation_effect_cancel_send(E_Zone *zone)
95 E_Event_Zone_Rotation_Effect_Cancel *ev;
97 ev = E_NEW(E_Event_Zone_Rotation_Effect_Cancel, 1);
101 ecore_event_add(E_EVENT_ZONE_ROTATION_EFFECT_CANCEL, ev, _rotation_effect_event_free, NULL);
103 EFFINF("Rotation Effect Event Cancel", NULL);
107 _rotation_effect_done_send(E_Zone *zone)
109 E_Event_Zone_Rotation_Effect_Done *ev;
111 ev = E_NEW(E_Event_Zone_Rotation_Effect_Done, 1);
115 ecore_event_add(E_EVENT_ZONE_ROTATION_EFFECT_DONE, ev, _rotation_effect_event_free, NULL);
117 EFFINF("Rotation Effect Event Done", NULL);
121 _rotation_effect_available(const E_Client *ec, int ang)
123 Eina_Bool ret = EINA_FALSE;
126 if (ang < 0) return EINA_FALSE;
127 if (!ec->e.state.rot.support)
130 if (ec->e.state.rot.preferred_rot == -1)
132 if (ec->e.state.rot.available_rots &&
133 ec->e.state.rot.count)
135 for (i = 0; i < ec->e.state.rot.count; i++)
137 if (ec->e.state.rot.available_rots[i] == ang)
147 else if (ec->e.state.rot.preferred_rot == ang)
156 _rotation_effect_targets_get(Rotation_Effect *effect, E_Desk *desk)
166 if (!effect) return NULL;
168 if (effect->zone->display_state == E_ZONE_DISPLAY_STATE_OFF)
173 t = eina_tiler_new(effect->zone->w + edge, effect->zone->h + edge);
174 eina_tiler_tile_size_set(t, 1, 1);
176 EINA_RECTANGLE_SET(&r, effect->zone->x, effect->zone->y, effect->zone->w, effect->zone->h);
177 eina_tiler_rect_add(t, &r);
179 o = evas_object_top_get(e_comp->evas);
180 for (; o; o = evas_object_below_get(o))
182 if (!evas_object_visible_get(o)) continue;
183 if (o == effect->zone->over) continue;
184 if (o == effect->bg) continue;
185 if (evas_object_layer_get(o) > E_LAYER_EFFECT) continue;
186 if (!e_util_strcmp(evas_object_name_get(o), "layer_obj")) continue;
188 evas_object_geometry_get(o, &x, &y, &w, &h);
189 ec = evas_object_data_get(o, "E_Client");
192 if (ec->desk != desk) continue;
193 if (e_object_is_del(E_OBJECT(ec))) continue;
194 if (ec->is_cursor) continue;
195 if (!E_INTERSECTS(ec->x, ec->y, ec->w, ec->h, ec->zone->x, ec->zone->y, ec->zone->w, ec->zone->h))
197 if ((ec->visibility.obscured != E_VISIBILITY_UNOBSCURED) &&
201 if ((!ec->animatable) ||
202 (e_client_video_client_has(ec)) ||
203 (!_rotation_effect_available(ec, effect->zone->rot.curr)) ||
204 (ec->e.state.rot.ang.curr == effect->zone->rot.curr))
206 if (l) eina_list_free(l);
212 l = eina_list_append(l, o);
214 if ((ec) && (ec->argb))
216 if (ec->visibility.opaque <= 0) continue;
219 if (ec->parent) continue;
223 EINA_RECTANGLE_SET(&r, x, y, w + edge, h + edge);
224 eina_tiler_rect_del(t, &r);
226 if (eina_tiler_empty(t)) break;
234 _rotation_effect_object_transform_pos_map(E_Client *ec, int sx, int sy, int *dx, int *dy)
236 E_Comp_Wl_Buffer_Viewport *vp = &ec->comp_data->scaler.buffer_viewport;
237 int transform = e_comp_wl_output_buffer_transform_get(ec);
240 e_pixmap_size_get(ec->pixmap, &bw, &bh);
242 /* for subsurface, it should be swap 90 and 270 */
243 if (ec->comp_data->sub.data)
246 case WL_OUTPUT_TRANSFORM_90: transform = WL_OUTPUT_TRANSFORM_270; break;
247 case WL_OUTPUT_TRANSFORM_270: transform = WL_OUTPUT_TRANSFORM_90; break;
248 case WL_OUTPUT_TRANSFORM_FLIPPED_90: transform = WL_OUTPUT_TRANSFORM_FLIPPED_270; break;
249 case WL_OUTPUT_TRANSFORM_FLIPPED_270: transform = WL_OUTPUT_TRANSFORM_FLIPPED_90; break;
255 case WL_OUTPUT_TRANSFORM_NORMAL:
256 default: tx = sx, ty = sy; break;
257 case WL_OUTPUT_TRANSFORM_90: tx = sy, ty = bw - sx; break;
258 case WL_OUTPUT_TRANSFORM_180: tx = bw - sx, ty = bh - sy; break;
259 case WL_OUTPUT_TRANSFORM_270: tx = bh - sy, ty = sx; break;
260 case WL_OUTPUT_TRANSFORM_FLIPPED: tx = bw - sx, ty = sy; break;
261 case WL_OUTPUT_TRANSFORM_FLIPPED_90: tx = sy, ty = sx; break;
262 case WL_OUTPUT_TRANSFORM_FLIPPED_180: tx = sx, ty = bh - sy; break;
263 case WL_OUTPUT_TRANSFORM_FLIPPED_270: tx = bh - sy, ty = bw - sx; break;
266 tx *= vp->buffer.scale;
267 ty *= vp->buffer.scale;
274 _rotation_effect_object_transform_apply(Rotation_Effect_Object *eobj)
278 int x1, y1, x2, y2, x, y, bw, bh;
281 int l, remain = sizeof buffer;
283 if (!(ec = eobj->ec)) return;
284 if (!ec->comp_data) return;
286 if (! e_comp_wl_output_buffer_transform_get(ec) &&
287 ec->comp_data->scaler.buffer_viewport.buffer.scale == 1)
290 map = evas_map_new(4);
293 e_pixmap_size_get(ec->pixmap, &bw, &bh);
299 evas_map_util_points_populate_from_geometry(map, ec->x, ec->y, bw, bh, 0);
301 _rotation_effect_object_transform_pos_map(ec, x1, y1, &x, &y);
302 evas_map_point_image_uv_set(map, 0, x, y);
303 l = snprintf(p, remain, " %d,%d", x, y);
306 _rotation_effect_object_transform_pos_map(ec, x2, y1, &x, &y);
307 evas_map_point_image_uv_set(map, 1, x, y);
308 l = snprintf(p, remain, " %d,%d", x, y);
311 _rotation_effect_object_transform_pos_map(ec, x2, y2, &x, &y);
312 evas_map_point_image_uv_set(map, 2, x, y);
313 l = snprintf(p, remain, " %d,%d", x, y);
316 _rotation_effect_object_transform_pos_map(ec, x1, y2, &x, &y);
317 evas_map_point_image_uv_set(map, 3, x, y);
318 l = snprintf(p, remain, " %d,%d", x, y);
321 evas_object_map_set(eobj->img, map);
322 evas_object_map_enable_set(eobj->img, EINA_TRUE);
328 _rotation_effect_object_free(Rotation_Effect_Object *eobj)
334 evas_object_image_data_set(eobj->img, NULL);
337 if (eobj->img) evas_object_del(eobj->img);
338 if (eobj->data_pool) wl_shm_pool_unref(eobj->data_pool);
343 static Rotation_Effect_Object *
344 _rotation_effect_object_create(Evas_Object *o)
346 Rotation_Effect_Object *eobj;
347 E_Comp_Wl_Buffer *buffer = NULL;
348 Evas_Object *img = NULL;
352 void *data = NULL, *pix = NULL;
354 if (!evas_object_visible_get(o)) return NULL;
356 ec = evas_object_data_get(o, "E_Client");
359 if (e_object_is_del(E_OBJECT(ec))) return NULL;
361 eobj = E_NEW(Rotation_Effect_Object, 1);
362 if (!eobj) goto fail;
366 buffer = e_pixmap_resource_get(ec->pixmap);
367 if (!buffer) goto fail;
369 img = evas_object_image_filled_add(e_comp->evas);
370 e_util_size_debug_set(img, 1);
371 evas_object_image_colorspace_set(img, EVAS_COLORSPACE_ARGB8888);
372 evas_object_image_smooth_scale_set(img, e_comp_config_get()->smooth_windows);
374 if (buffer->type == E_COMP_WL_BUFFER_TYPE_SHM)
376 if (!buffer->shm_buffer) goto fail;
381 pix = wl_shm_buffer_get_data(buffer->shm_buffer);
385 wl_shm_pool_unref(eobj->data_pool);
386 eobj->data_pool = wl_shm_buffer_ref_pool(buffer->shm_buffer);
388 else if (buffer->type == E_COMP_WL_BUFFER_TYPE_NATIVE)
390 tbm_surface_info_s surface_info;
391 tbm_surface_h tbm_surface = wayland_tbm_server_get_surface(NULL, buffer->resource);
392 memset(&surface_info, 0, sizeof(tbm_surface_info_s));
393 tbm_surface_map(tbm_surface, TBM_SURF_OPTION_READ, &surface_info);
395 data = surface_info.planes[0].ptr;
396 if (!data) goto fail;
398 w = surface_info.width;
399 h = surface_info.height;
401 pix = eobj->data = malloc(w * h * 4);
402 for (i = 0; i < h; i++)
404 memcpy(pix, data, surface_info.width * 4);
405 pix += surface_info.width * 4;
406 data += surface_info.planes[0].stride;
410 tbm_surface_unmap(tbm_surface);
412 else if (buffer->type == E_COMP_WL_BUFFER_TYPE_TBM)
414 tbm_surface_info_s surface_info;
415 tbm_surface_h tbm_surface = buffer->tbm_surface;
417 memset(&surface_info, 0, sizeof(tbm_surface_info_s));
418 tbm_surface_map(tbm_surface, TBM_SURF_OPTION_READ, &surface_info);
420 data = surface_info.planes[0].ptr;
421 if (!data) goto fail;
423 w = surface_info.width;
424 h = surface_info.height;
426 pix = eobj->data = malloc(w * h * 4);
427 for (i = 0; i < h; i++)
429 memcpy(pix, data, surface_info.width * 4);
430 pix += surface_info.width * 4;
431 data += surface_info.planes[0].stride;
435 tbm_surface_unmap(tbm_surface);
443 evas_object_image_alpha_set(img, 1);
444 evas_object_image_size_set(img, w, h);
445 evas_object_image_data_set(img, pix);
446 evas_object_image_data_update_add(img, 0, 0, w, h);
448 evas_object_name_set(img, "rotation-effect-image");
449 evas_object_move(img, ec->x, ec->y);
450 evas_object_resize(img, ec->w, ec->h);
455 EFFINF("Rotation EFFECT Object Created E_Client:%p",
463 eobj = E_NEW(Rotation_Effect_Object, 1);
464 if (!eobj) return NULL;
468 evas_object_geometry_get(o, &x, &y, &w, &h);
470 img = evas_object_image_filled_add(e_comp->evas);
471 e_util_size_debug_set(img, 1);
473 evas_object_image_colorspace_set(img, EVAS_COLORSPACE_ARGB8888);
474 evas_object_image_smooth_scale_set(img, e_comp_config_get()->smooth_windows);
475 evas_object_image_alpha_set(img, 1);
476 evas_object_image_size_set(img, w, h);
477 evas_object_image_source_set(img, o);
479 evas_object_name_set(img, "rotation-effect-image");
480 evas_object_move(img, x, y);
481 evas_object_resize(img, w, h);
485 EFFINF("Rotation EFFECT Object Created Object:%p",
494 evas_object_image_data_set(img, NULL);
495 evas_object_del(img);
501 wl_shm_pool_unref(eobj->data_pool);
509 static Rotation_Effect_Begin_Context *
510 _rotation_effect_begin_create(Rotation_Effect *effect, Eina_List *targets, E_Desk *desk)
512 Rotation_Effect_Begin_Context *ctx_begin = NULL;
513 Rotation_Effect_Object *eobj = NULL;
518 ctx_begin = E_NEW(Rotation_Effect_Begin_Context, 1);
519 if (!ctx_begin) return NULL;
521 ctx_begin->layout = e_layout_add(e_comp->evas);
522 e_util_size_debug_set(ctx_begin->layout, 1);
523 evas_object_name_set(ctx_begin->layout, "rotation-begin-effect-layout");
524 e_layout_virtual_size_set(ctx_begin->layout, effect->zone->w, effect->zone->h);
525 evas_object_move(ctx_begin->layout, effect->zone->x, effect->zone->y);
526 evas_object_resize(ctx_begin->layout, effect->zone->w, effect->zone->h);
527 evas_object_layer_set(ctx_begin->layout, E_LAYER_EFFECT);
529 EINA_LIST_REVERSE_FOREACH(targets, l, target)
531 eobj = _rotation_effect_object_create(target);
534 _rotation_effect_object_transform_apply(eobj);
536 ctx_begin->objects = eina_list_append(ctx_begin->objects, eobj);
538 effect->waiting_list = eina_list_append(effect->waiting_list, eobj->ec);
540 evas_object_geometry_get(target, &x, &y, &w, &h);
542 e_layout_pack(ctx_begin->layout, eobj->img);
543 e_layout_child_move(eobj->img, x, y);
544 e_layout_child_resize(eobj->img, w, h);
545 e_layout_child_raise(eobj->img);
546 evas_object_show(eobj->img);
549 if (!ctx_begin->objects)
551 evas_object_del(ctx_begin->layout);
556 e_desk_smart_member_add(desk, ctx_begin->layout);
558 EFFINF("Rotation Begin Created", NULL);
560 int diff = effect->zone->rot.prev - effect->zone->rot.curr;
561 if (diff == 270) diff = - 90;
562 else if (diff == -270) diff = 90;
563 ctx_begin->src = 0.0;
564 ctx_begin->dest = diff;
570 static Rotation_Effect_End_Context *
571 _rotation_effect_end_create(Rotation_Effect *effect, Eina_List *targets, E_Desk *desk)
573 Rotation_Effect_End_Context *ctx_end = NULL;
574 Rotation_Effect_Object *eobj = NULL;
579 ctx_end = E_NEW(Rotation_Effect_End_Context, 1);
580 if (!ctx_end) return NULL;
582 ctx_end->layout = e_layout_add(e_comp->evas);
583 e_util_size_debug_set(ctx_end->layout, 1);
584 evas_object_name_set(ctx_end->layout, "rotation-end-effect-layout");
585 e_layout_virtual_size_set(ctx_end->layout, effect->zone->w, effect->zone->h);
586 evas_object_move(ctx_end->layout, effect->zone->x, effect->zone->y);
587 evas_object_resize(ctx_end->layout, effect->zone->w, effect->zone->h);
588 evas_object_layer_set(ctx_end->layout, E_LAYER_EFFECT);
590 EINA_LIST_REVERSE_FOREACH(targets, l, target)
592 eobj = _rotation_effect_object_create(target);
595 _rotation_effect_object_transform_apply(eobj);
597 evas_object_geometry_get(target, &x, &y, &w, &h);
599 ctx_end->objects = eina_list_append(ctx_end->objects, eobj);
601 e_layout_pack(ctx_end->layout, eobj->img);
602 e_layout_child_move(eobj->img, x, y);
603 e_layout_child_resize(eobj->img, w, h);
604 e_layout_child_raise(eobj->img);
605 evas_object_show(eobj->img);
608 if (!ctx_end->objects)
610 evas_object_del(ctx_end->layout);
615 e_desk_smart_member_add(desk, ctx_end->layout);
617 EFFINF("Rotation End Created", NULL);
619 int diff = _rotation_zone->curr_angle - _rotation_zone->prev_angle;
620 if (diff == 270) diff = - 90;
621 else if (diff == -270) diff = 90;
629 _rotation_effect_animator_begin_context_free(Rotation_Effect_Begin_Context *ctx_begin)
631 Rotation_Effect_Object *eobj;
633 if (!ctx_begin) return;
635 EFFINF("Rotation Begin Free", NULL);
637 if (ctx_begin->layout)
638 evas_object_hide(ctx_begin->layout);
640 EINA_LIST_FREE(ctx_begin->objects, eobj)
642 e_layout_unpack(eobj->img);
643 _rotation_effect_object_free(eobj);
646 if (ctx_begin->layout)
647 evas_object_del(ctx_begin->layout);
653 _rotation_effect_animator_end_context_free(Rotation_Effect_End_Context *ctx_end)
655 Rotation_Effect_Object *eobj;
657 if (!ctx_end) return;
659 EFFINF("Rotation End Free", NULL);
662 evas_object_hide(ctx_end->layout);
664 EINA_LIST_FREE(ctx_end->objects, eobj)
666 e_layout_unpack(eobj->img);
667 _rotation_effect_object_free(eobj);
671 evas_object_del(ctx_end->layout);
677 _rotation_effect_clear(Rotation_Effect *effect)
681 EFFINF("Rotation Effect Clear", NULL);
683 effect->targets = eina_list_free(effect->targets);
684 effect->waiting_list = eina_list_free(effect->waiting_list);
686 if (effect->animator)
687 ecore_animator_del(effect->animator);
689 evas_object_hide(effect->bg);
691 if (effect->ctx_begin)
693 _rotation_effect_animator_begin_context_free(effect->ctx_begin);
694 e_comp_override_del();
699 _rotation_effect_animator_end_context_free(effect->ctx_end);
700 _rotation_effect_done_send(effect->zone);
703 effect->running = EINA_FALSE;
704 effect->wait_for_buffer = EINA_FALSE;
705 effect->animator = NULL;
706 effect->ctx_begin = NULL;
707 effect->ctx_end = NULL;
711 _rotation_effect_animator_cb_update(void *data, double pos)
713 Rotation_Effect *effect;
714 Rotation_Effect_Begin_Context *ctx_begin;
715 Rotation_Effect_End_Context *ctx_end;
717 double curr, col, progress;
718 Evas_Coord x, y, w, h;
720 effect = (Rotation_Effect *)data;
721 ctx_begin = effect->ctx_begin;
722 ctx_end = effect->ctx_end;
726 ecore_animator_del(effect->animator);
727 effect->animator = NULL;
729 _rotation_effect_animator_begin_context_free(effect->ctx_begin);
730 effect->ctx_begin = NULL;
732 _rotation_effect_animator_end_context_free(effect->ctx_end);
733 effect->ctx_end = NULL;
735 effect->wait_for_buffer = EINA_FALSE;
736 effect->running = EINA_FALSE;
737 evas_object_hide(effect->bg);
739 e_comp_override_del();
740 _rotation_effect_done_send(effect->zone);
742 return ECORE_CALLBACK_CANCEL;
745 progress = ecore_animator_pos_map(pos, ECORE_POS_MAP_DECELERATE, 0, 0);
747 if (progress < 0.0) progress = 0.0;
750 curr = (progress * ctx_begin->dest);
751 col = 255 - (255 * progress);
753 evas_object_geometry_get(ctx_begin->layout, &x, &y, &w, &h);
755 Evas_Map *m = evas_map_new(4);
756 evas_map_util_points_populate_from_object(m, ctx_begin->layout);
757 evas_map_util_rotate(m, curr, x + (w/2), y + (h/2));
758 evas_map_alpha_set(m, EINA_TRUE);
759 evas_map_util_points_color_set(m, col, col, col, col);
760 evas_object_map_set(ctx_begin->layout, m);
761 evas_object_map_enable_set(ctx_begin->layout, EINA_TRUE);
765 curr = ((-1.0f * progress * ctx_end->src) + ctx_end->src);
767 evas_object_geometry_get(ctx_end->layout, &x, &y, &w, &h);
770 evas_map_util_points_populate_from_object(m, ctx_end->layout);
771 evas_map_util_rotate(m, curr, x + (w/2), y + (h/2));
772 evas_object_map_set(ctx_end->layout, m);
773 evas_object_map_enable_set(ctx_end->layout, EINA_TRUE);
776 return ECORE_CALLBACK_RENEW;
780 _norender_timer_timeout(void *data)
782 Rotation_Effect *effect = (Rotation_Effect *)data;
784 effect->norender_timer = NULL;
785 effect->norender = EINA_FALSE;
787 EFFINF("EFF norender pop - timeout", NULL);
789 e_comp_canvas_norender_pop();
791 return ECORE_CALLBACK_CANCEL;
795 _rotation_effect_start(Rotation_Effect *effect)
797 if ((!effect->ctx_begin) || (!effect->ctx_end)) return;
798 if (effect->running) return;
800 /* now, we're going to start rotation effect.
801 * so, unblock updating canvas (compositing mode)
803 if (effect->norender)
805 if (effect->norender_timer)
806 ecore_timer_del(effect->norender_timer);
808 effect->norender_timer = NULL;
809 effect->norender = EINA_FALSE;
811 EFFINF("EFF norender pop - start", NULL);
813 e_comp_canvas_norender_pop();
816 EFFINF("Rotation Effect Start", NULL);
818 effect->running = EINA_TRUE;
820 evas_object_raise(effect->ctx_begin->layout);
821 evas_object_show(effect->ctx_begin->layout);
822 evas_object_show(effect->ctx_end->layout);
824 evas_object_move(effect->bg, 0, 0);
825 evas_object_resize(effect->bg, effect->zone->w, effect->zone->h);
826 evas_object_lower(effect->bg);
827 evas_object_show(effect->bg);
829 effect->animator = ecore_animator_timeline_add(0.3f,
830 _rotation_effect_animator_cb_update,
835 _rotation_effect_animator_begin_prepare(Rotation_Effect *effect, E_Desk *desk)
839 _rotation_effect_clear(effect);
841 effect->targets = _rotation_effect_targets_get(effect, desk);
842 if (!effect->targets) return;
844 effect->ctx_begin = _rotation_effect_begin_create(effect, effect->targets, desk);
845 if (!effect->ctx_begin)
847 _rotation_effect_clear(effect);
851 EFFINF("Rotation Begin Prepared", NULL);
853 /* add hwc override */
854 e_comp_override_add();
856 /* block updating canvas (compositing mode) to avoid showing rotated window that
857 * could be outputted to the screen before starting rotation effect.
858 * it will be unset when the rotation effect starts.
860 if (!effect->norender)
862 EFFINF("EFF norender push ", NULL);
864 e_comp_canvas_norender_push();
866 if (effect->norender_timer)
867 ecore_timer_del(effect->norender_timer);
869 effect->norender_timer = ecore_timer_add(1.0f,
870 _norender_timer_timeout,
873 effect->norender = EINA_TRUE;
878 _rotation_effect_animator_end_prepare(Rotation_Effect *effect, E_Desk *desk)
881 if (!effect->targets) return;
882 if (!effect->ctx_begin) return;
884 /* clear previous context */
886 _rotation_effect_animator_end_context_free(effect->ctx_end);
887 effect->ctx_end = NULL;
889 effect->ctx_end = _rotation_effect_end_create(effect, effect->targets, desk);
890 if (!effect->ctx_end) return;
892 EFFINF("Rotation End Prepared", NULL);
894 effect->targets = eina_list_free(effect->targets);
898 _rotation_effect_cb_zone_rotation_begin(void *data, int type, void *event)
900 Rotation_Effect *effect;
901 E_Event_Zone_Rotation_Change_Begin *ev = event;
905 effect = (Rotation_Effect *)data;
906 if (!effect) return ECORE_CALLBACK_PASS_ON;
909 if (!zone) return ECORE_CALLBACK_PASS_ON;
911 EFFINF("Zone rotation begin zone(prev:%d cur:%d)",
913 zone->rot.prev, zone->rot.curr);
915 if (zone->rot.prev == zone->rot.curr) return ECORE_CALLBACK_PASS_ON;
917 _rotation_zone->curr_angle = zone->rot.curr;
918 _rotation_zone->prev_angle = zone->rot.prev;
920 desk = e_desk_current_get(zone);
921 _rotation_effect_animator_begin_prepare(effect, desk);
924 _rotation_effect_ready_send(zone);
926 return ECORE_CALLBACK_PASS_ON;
930 _rotation_effect_cb_zone_rotation_end(void *data, int type, void *event)
932 Rotation_Effect *effect;
933 E_Event_Zone_Rotation_Change_End *ev = event;
937 effect = (Rotation_Effect *)data;
938 if (!effect) return ECORE_CALLBACK_PASS_ON;
941 if (!zone) return ECORE_CALLBACK_PASS_ON;
943 EFFINF("Zone rotation end angle(prev:%d cur:%d)", NULL,
944 zone->rot.prev, zone->rot.curr);
946 if (effect->running) return ECORE_CALLBACK_PASS_ON;
947 if (effect->waiting_list)
949 effect->wait_for_buffer = EINA_TRUE;
950 return ECORE_CALLBACK_PASS_ON;
953 if (!effect->ctx_end)
955 desk = e_desk_current_get(zone);
956 _rotation_effect_animator_end_prepare(effect, desk);
958 if (!effect->ctx_end)
959 _rotation_effect_clear(effect);
961 if (effect->ctx_end) _rotation_effect_start(effect);
963 return ECORE_CALLBACK_PASS_ON;
967 _rotation_effect_cb_zone_rotation_cancel(void *data, int type, void *event)
969 E_Event_Zone_Rotation_Change_Cancel *ev = event;
970 Rotation_Effect *effect;
974 if (!zone) return ECORE_CALLBACK_PASS_ON;
976 effect = (Rotation_Effect *)data;
977 if (!effect) return ECORE_CALLBACK_PASS_ON;
979 EFFINF("Zone Rotation Cancelled", NULL);
981 if (effect->running) return ECORE_CALLBACK_PASS_ON;
982 if (effect->targets) _rotation_effect_cancel_send(zone);
984 if (effect->norender)
986 if (effect->norender_timer)
987 ecore_timer_del(effect->norender_timer);
989 effect->norender_timer = NULL;
990 effect->norender = EINA_FALSE;
992 EFFINF("EFF norender pop - cancel", NULL);
994 e_comp_canvas_norender_pop();
997 _rotation_effect_clear(effect);
999 return ECORE_CALLBACK_PASS_ON;
1003 _rotation_effect_cb_buffer_change(void *data, int ev_type, void *event)
1005 E_Event_Client *ev = event;
1008 Rotation_Effect *effect;
1011 if (!ec) return ECORE_CALLBACK_PASS_ON;
1013 effect = (Rotation_Effect *)data;
1014 if (!effect) return ECORE_CALLBACK_PASS_ON;
1015 if (!effect->ctx_begin) return ECORE_CALLBACK_PASS_ON;
1016 if (!effect->waiting_list) return ECORE_CALLBACK_PASS_ON;
1018 effect->waiting_list = eina_list_remove(effect->waiting_list, ec);
1019 if (effect->waiting_list) return ECORE_CALLBACK_PASS_ON;
1021 if (!effect->wait_for_buffer) return ECORE_CALLBACK_PASS_ON;
1023 if (!effect->ctx_end)
1025 desk = e_desk_current_get(ec->zone);
1026 _rotation_effect_animator_end_prepare(effect, desk);
1028 if (effect->ctx_end) _rotation_effect_start(effect);
1030 return ECORE_CALLBACK_PASS_ON;
1034 _rotation_effect_cb_client_hide(void *data, int ev_type, void *event)
1036 E_Event_Client *ev = event;
1038 Rotation_Effect *effect;
1042 if (!ec) return ECORE_CALLBACK_PASS_ON;
1044 effect = (Rotation_Effect *)data;
1045 if (!effect) return ECORE_CALLBACK_PASS_ON;
1046 if (!effect->ctx_begin) return ECORE_CALLBACK_PASS_ON;
1047 if (!effect->waiting_list) return ECORE_CALLBACK_PASS_ON;
1049 effect->waiting_list = eina_list_remove(effect->waiting_list, ec);
1050 if (effect->waiting_list) return ECORE_CALLBACK_PASS_ON;
1052 if (!effect->wait_for_buffer) return ECORE_CALLBACK_PASS_ON;
1054 if (!effect->ctx_end)
1056 desk = e_desk_current_get(ec->zone);
1057 _rotation_effect_animator_end_prepare(effect, desk);
1059 if (effect->ctx_end) _rotation_effect_start(effect);
1061 return ECORE_CALLBACK_PASS_ON;
1065 _rotation_effect_cb_client_remove(void *data, int ev_type, void *event)
1067 E_Event_Client *ev = event;
1069 Rotation_Effect *effect;
1070 Rotation_Effect_Object *eobj;
1072 Eina_Bool clear = EINA_FALSE;
1075 if (!ec) return ECORE_CALLBACK_PASS_ON;
1077 effect = (Rotation_Effect *)data;
1078 if (!effect) return ECORE_CALLBACK_PASS_ON;
1079 if (effect->ctx_begin)
1081 EINA_LIST_FOREACH(effect->ctx_begin->objects, l, eobj)
1091 _rotation_effect_clear(effect);
1094 return ECORE_CALLBACK_PASS_ON;
1098 _rotation_effect_free(Rotation_Effect *effect)
1100 if (!effect) return;
1102 if (effect->norender_timer)
1103 ecore_timer_del(effect->norender_timer);
1104 effect->norender_timer = NULL;
1105 if (effect->norender)
1107 EFFINF("EFF norender pop - free", NULL);
1109 e_comp_canvas_norender_pop();
1111 effect->norender = EINA_FALSE;
1113 _rotation_effect_clear(effect);
1114 evas_object_del(effect->bg);
1118 static Rotation_Effect *
1119 _rotation_effect_create(E_Zone *zone)
1121 Rotation_Effect *rotation_effect;
1123 rotation_effect = E_NEW(Rotation_Effect, 1);
1124 if (!rotation_effect) return NULL;
1126 rotation_effect->zone = zone;
1128 rotation_effect->bg = evas_object_rectangle_add(e_comp->evas);
1129 e_util_size_debug_set(rotation_effect->bg, 1);
1130 evas_object_color_set(rotation_effect->bg, 0, 0, 0, 255);
1131 evas_object_layer_set(rotation_effect->bg, E_LAYER_EFFECT);
1132 evas_object_name_set(rotation_effect->bg, "rotation-bg");
1134 return rotation_effect;
1138 _rotation_zone_free(Rotation_Zone *rotation_zone)
1140 if (!rotation_zone) return;
1142 E_FREE_LIST(rotation_zone->event_hdlrs, ecore_event_handler_del);
1144 _rotation_effect_free(rotation_zone->effect);
1146 E_FREE(rotation_zone);
1151 static Rotation_Zone *
1152 _rotation_zone_create(E_Zone *zone)
1154 Rotation_Zone *rotation_zone = NULL;
1156 if (!zone) return NULL;
1157 if ((zone->w == 0) || (zone->h == 0)) return NULL;
1159 rotation_zone = E_NEW(Rotation_Zone, 1);
1160 if (!rotation_zone) return NULL;
1162 /* create rotation effect data */
1163 rotation_zone->effect = _rotation_effect_create(zone);
1164 if (!rotation_zone->effect)
1166 E_FREE(rotation_zone);
1170 rotation_zone->zone = zone;
1171 rotation_zone->curr_angle = zone->rot.curr;
1172 rotation_zone->prev_angle = zone->rot.prev;
1174 E_LIST_HANDLER_APPEND(rotation_zone->event_hdlrs,
1175 E_EVENT_ZONE_ROTATION_CHANGE_BEGIN,
1176 _rotation_effect_cb_zone_rotation_begin, rotation_zone->effect);
1178 E_LIST_HANDLER_APPEND(rotation_zone->event_hdlrs,
1179 E_EVENT_ZONE_ROTATION_CHANGE_END,
1180 _rotation_effect_cb_zone_rotation_end, rotation_zone->effect);
1182 E_LIST_HANDLER_APPEND(rotation_zone->event_hdlrs,
1183 E_EVENT_ZONE_ROTATION_CHANGE_CANCEL,
1184 _rotation_effect_cb_zone_rotation_cancel, rotation_zone->effect);
1186 E_LIST_HANDLER_APPEND(rotation_zone->event_hdlrs,
1187 E_EVENT_CLIENT_BUFFER_CHANGE,
1188 _rotation_effect_cb_buffer_change, rotation_zone->effect);
1190 E_LIST_HANDLER_APPEND(rotation_zone->event_hdlrs,
1191 E_EVENT_CLIENT_HIDE,
1192 _rotation_effect_cb_client_hide, rotation_zone->effect);
1194 E_LIST_HANDLER_APPEND(rotation_zone->event_hdlrs,
1195 E_EVENT_CLIENT_REMOVE,
1196 _rotation_effect_cb_client_remove, rotation_zone->effect);
1198 return rotation_zone;
1202 e_mod_effect_rotation_init(void)
1204 _rotation_zone = _rotation_zone_create(e_zone_current_get());
1205 if (!_rotation_zone) return EINA_FALSE;
1211 e_mod_effect_rotation_shutdown(void)
1214 _rotation_zone_free(_rotation_zone);
1216 _rotation_zone = NULL;