redesign the cursor rendering
[platform/upstream/enlightenment.git] / src / bin / e_pointer.c
1 #include "e.h"
2
3 /* local variables */
4 static Eina_List *_ptrs = NULL;
5 static Eina_Bool _initted = EINA_FALSE;
6
7 static void
8 _e_pointer_map_transform(int width, int height, uint32_t transform,
9                          int sx, int sy, int *dx, int *dy)
10 {
11    switch (transform)
12      {
13       case WL_OUTPUT_TRANSFORM_NORMAL:
14       default:
15         *dx = sx, *dy = sy;
16         break;
17       case WL_OUTPUT_TRANSFORM_90:
18         *dx = height - sy, *dy = sx;
19         break;
20       case WL_OUTPUT_TRANSFORM_180:
21         *dx = width - sx, *dy = height - sy;
22         break;
23       case WL_OUTPUT_TRANSFORM_270:
24         *dx = sy, *dy = width - sx;
25         break;
26      }
27 }
28
29 static void
30 _e_pointer_rotation_apply(E_Pointer *ptr)
31 {
32    Evas_Map *map;
33    int x1, y1, x2, y2, dx, dy;
34    int32_t width, height;
35    int cursor_w, cursor_h;
36    uint32_t transform;
37    int rot_x, rot_y, x, y;
38    int zone_w, zone_h;
39    double awh, ahw;
40    E_Client *ec;
41    int rotation;
42
43    EINA_SAFETY_ON_NULL_RETURN(ptr);
44    if (!ptr->o_ptr) return;
45
46    ec = e_comp_object_client_get(ptr->o_ptr);
47    EINA_SAFETY_ON_NULL_RETURN(ec);
48
49    x = ptr->x;
50    y = ptr->y;
51    rotation = ptr->rotation;
52
53    evas_object_geometry_get(ec->frame, NULL, NULL, &cursor_w, &cursor_h);
54
55    if ((rotation == 0) || (rotation % 90 != 0) || (rotation / 90 > 3))
56      {
57         evas_object_map_set(ec->frame, NULL);
58         evas_object_map_enable_set(ec->frame, EINA_FALSE);
59         evas_object_move(ec->frame, x, y);
60         return;
61      }
62
63    zone_w = ec->zone->w;
64    zone_h = ec->zone->h;
65    awh = ((double)zone_w / (double)zone_h);
66    ahw = ((double)zone_h / (double)zone_w);
67
68    rot_x = x;
69    rot_y = y;
70    width = cursor_w;
71    height = cursor_h;
72
73    switch(rotation)
74      {
75       case 90:
76          rot_x = y * awh;
77          rot_y = ahw * (zone_w - x);
78          transform = WL_OUTPUT_TRANSFORM_90;
79          width = cursor_h;
80          height = cursor_w;
81          break;
82       case 180:
83          rot_x = zone_w - x;
84          rot_y = zone_h - y;
85          transform = WL_OUTPUT_TRANSFORM_180;
86          break;
87       case 270:
88          rot_x = awh * (zone_h - y);
89          rot_y = ahw * x;
90          transform = WL_OUTPUT_TRANSFORM_270;
91          width = cursor_h;
92          height = cursor_w;
93          break;
94       default:
95          transform = WL_OUTPUT_TRANSFORM_NORMAL;
96          break;
97      }
98
99    if (ptr->device == E_POINTER_MOUSE)
100      {
101         ec->client.x = rot_x, ec->client.y = rot_y;
102         ec->x = rot_x, ec->y = rot_y;
103         ptr->x = rot_x;
104         ptr->y = rot_y;
105      }
106
107    map = evas_map_new(4);
108    evas_map_util_points_populate_from_geometry(map,
109                                                ec->x, ec->y,
110                                                width, height, 0);
111
112    x1 = 0.0;
113    y1 = 0.0;
114    x2 = width;
115    y2 = height;
116
117    _e_pointer_map_transform(width, height, transform,
118                             x1, y1, &dx, &dy);
119    evas_map_point_image_uv_set(map, 0, dx, dy);
120
121    _e_pointer_map_transform(width, height, transform,
122                             x2, y1, &dx, &dy);
123    evas_map_point_image_uv_set(map, 1, dx, dy);
124
125    _e_pointer_map_transform(width, height, transform,
126                             x2, y2, &dx, &dy);
127    evas_map_point_image_uv_set(map, 2, dx, dy);
128
129    _e_pointer_map_transform(width, height, transform,
130                             x1, y2, &dx, &dy);
131    evas_map_point_image_uv_set(map, 3, dx, dy);
132
133    evas_object_map_set(ec->frame, map);
134    evas_object_map_enable_set(ec->frame, map ? EINA_TRUE : EINA_FALSE);
135
136    evas_map_free(map);
137 }
138
139 static void
140 _e_pointer_cb_free(E_Pointer *ptr)
141 {
142    _ptrs = eina_list_remove(_ptrs, ptr);
143
144    free(ptr);
145 }
146
147 EINTERN int
148 e_pointer_init(void)
149 {
150    _initted = EINA_TRUE;
151    return 1;
152 }
153
154 EINTERN int
155 e_pointer_shutdown(void)
156 {
157    _initted = EINA_FALSE;
158    return 1;
159 }
160
161 EINTERN E_Pointer *
162 e_pointer_canvas_new(Ecore_Evas *ee, Eina_Bool filled)
163 {
164    E_Pointer *ptr = NULL;
165
166    EINA_SAFETY_ON_FALSE_RETURN_VAL(ee, NULL);
167    if (!_initted) return NULL;
168
169    /* allocate space for new pointer */
170    if (!(ptr = E_OBJECT_ALLOC(E_Pointer, E_POINTER_TYPE, _e_pointer_cb_free)))
171      return NULL;
172
173    /* set default pointer properties */
174    ptr->canvas = EINA_TRUE;
175    ptr->w = ptr->h = e_config->cursor_size;
176    ptr->e_cursor = e_config->use_e_cursor;
177
178    ptr->ee = ee;
179    ptr->evas = ecore_evas_get(ee);
180
181    /* append this pointer to the list */
182    _ptrs = eina_list_append(_ptrs, ptr);
183
184    return ptr;
185 }
186
187 EINTERN void
188 e_pointer_object_set(E_Pointer *ptr, Evas_Object *obj, int x, int y)
189 {
190    E_Client *ec;
191
192    EINA_SAFETY_ON_NULL_RETURN(ptr);
193
194    /* don't show cursor if in hidden mode */
195    if ((!e_config->show_cursor) || (!e_comp_wl->ptr.enabled))
196      {
197         e_pointer_hide(ptr);
198         return;
199      }
200
201    /* hide and unset the existed ptr->o_ptr */
202    if (ptr->o_ptr)
203      {
204         ec = e_comp_object_client_get(ptr->o_ptr);
205         if (ec)
206           {
207              ec->hidden = 1;
208              ec->visible = EINA_FALSE;
209              ec->comp_data->mapped = EINA_FALSE;
210              ec->override = 1; /* ignore the previous cursor_ec */
211           }
212
213         /* hide cursor object */
214         evas_object_hide(ptr->o_ptr);
215         ptr->o_ptr = NULL;
216         ptr->device = E_POINTER_NONE;
217      }
218
219    /* if obj is not null, set the obj to ptr->o_ptr */
220    if (obj)
221      {
222         ec = e_comp_object_client_get(obj);
223         if (ec)
224           {
225              ec->hidden = 0;
226              ec->visible = EINA_TRUE;
227              ec->comp_data->mapped = EINA_TRUE;
228              ec->override = 0; /* do not ignore the cursor_ec to set the image object */
229           }
230
231         /* apply the cursor obj rotation */
232         _e_pointer_rotation_apply(ptr);
233
234         /* move the pointer to the current position */
235         evas_object_move(obj, ptr->x, ptr->y);
236
237         /* show cursor object */
238         evas_object_show(obj);
239         ptr->o_ptr = obj;
240      }
241 }
242
243 EINTERN void
244 e_pointer_touch_move(E_Pointer *ptr, int x, int y)
245 {
246    EINA_SAFETY_ON_NULL_RETURN(ptr);
247
248    if (!e_config->show_cursor) return;
249    if (!ptr->o_ptr) return;
250    if (!evas_object_visible_get(ptr->o_ptr)) return;
251
252    /* save the current position */
253    ptr->x = x;
254    ptr->y = y;
255
256    if (ptr->device != E_POINTER_TOUCH) ptr->device = E_POINTER_TOUCH;
257
258    _e_pointer_rotation_apply(ptr);
259    evas_object_move(ptr->o_ptr, ptr->x, ptr->y);
260 }
261
262 EINTERN void
263 e_pointer_mouse_move(E_Pointer *ptr, int x, int y)
264 {
265    EINA_SAFETY_ON_NULL_RETURN(ptr);
266
267    if (!e_config->show_cursor) return;
268    if (!ptr->o_ptr) return;
269    if (!evas_object_visible_get(ptr->o_ptr)) return;
270
271    /* save the current position */
272    ptr->x = x;
273    ptr->y = y;
274
275    if (ptr->device != E_POINTER_MOUSE) ptr->device = E_POINTER_MOUSE;
276
277    _e_pointer_rotation_apply(ptr);
278    evas_object_move(ptr->o_ptr, ptr->x, ptr->y);
279 }
280
281 E_API void
282 e_pointer_hide(E_Pointer *ptr)
283 {
284    EINA_SAFETY_ON_NULL_RETURN(ptr);
285    if (ptr->o_ptr) return;
286
287    evas_object_hide(ptr->o_ptr);
288 }
289
290 E_API Eina_Bool
291 e_pointer_is_hidden(E_Pointer *ptr)
292 {
293    EINA_SAFETY_ON_NULL_RETURN_VAL(ptr, EINA_TRUE);
294
295    if (!e_config->show_cursor) return EINA_TRUE;
296    if (ptr->o_ptr && evas_object_visible_get(ptr->o_ptr)) return EINA_FALSE;
297
298    return EINA_TRUE;
299 }
300
301 E_API void
302 e_pointer_rotation_set(E_Pointer *ptr, int rotation)
303 {
304    ptr->rotation = rotation;
305
306    _e_pointer_rotation_apply(ptr);
307    evas_object_move(ptr->o_ptr, ptr->x, ptr->y);
308 }
309
310 E_API void
311 e_pointer_position_get(E_Pointer *ptr, int *x, int *y)
312 {
313    EINA_SAFETY_ON_NULL_RETURN(ptr);
314
315    if (!e_config->show_cursor) return;
316    if (!ptr->o_ptr) return;
317    if (!evas_object_visible_get(ptr->o_ptr)) return;
318
319    *x = ptr->x;
320    *y = ptr->y;
321 }
322