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