summaryrefslogtreecommitdiff
path: root/src/lib/evas_debug.c
blob: 9543b93d5e93c47eec12a720a9a63c352164b7d6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
#include <Eina.h>
#include <Ecore.h>
#include <Ecore_X.h>
#include <Evas.h>
#include <Elementary.h>

#include "Evas_Debug.h"

#define STORE(_buf, pval, sz) \
{ \
   memcpy(_buf, pval, sz); \
   _buf += sz; \
}

#define EXTRACT(_buf, pval, sz) \
{ \
   memcpy(pval, _buf, sz); \
   _buf += sz; \
}
enum {
   HIGHLIGHT_R = 255,
   HIGHLIGHT_G = 128,
   HIGHLIGHT_B = 128,
   HIGHLIGHT_A = 255
};

static int _obj_highlight_op = EINA_DEBUG_OPCODE_INVALID;
static int _win_screenshot_op = EINA_DEBUG_OPCODE_INVALID;

/* Highlight functions. */
static Eina_Bool
_obj_highlight_fade(void *_rect)
{
   Evas_Object *rect = _rect;
   int r, g, b, a;
   double na;

   evas_object_color_get(rect, &r, &g, &b, &a);
   if (a < 20)
     {
        evas_object_del(rect);
        /* The del callback of the object will destroy the animator */
        return EINA_TRUE;
     }

   na = a - 5;
   r = na / a * r;
   g = na / a * g;
   b = na / a * b;
   evas_object_color_set(rect, r, g, b, na);

   return EINA_TRUE;
}

static void
_obj_highlight_del(void *data,
      EINA_UNUSED Evas *e,
      EINA_UNUSED Evas_Object *obj,
      EINA_UNUSED void *event_info)
{  /* Delete timer for this rect */
   ecore_animator_del(data);
}

static Eina_Debug_Error
_obj_highlight_cb(Eina_Debug_Session *session EINA_UNUSED, int srcid EINA_UNUSED, void *buffer, int size)
{
   if (size <= 0) return EINA_DEBUG_ERROR;
   uint64_t ptr64;
   memcpy(&ptr64, buffer, sizeof(ptr64));
   Eo *obj = (Eo *)ptr64;
   if (!efl_isa(obj, EFL_CANVAS_OBJECT_CLASS) && !efl_isa(obj, EVAS_CANVAS_CLASS)) return EINA_DEBUG_OK;
   Evas *e = evas_object_evas_get(obj);
   Eo *rect = evas_object_polygon_add(e);
   evas_object_move(rect, 0, 0);
   if (efl_isa(obj, EFL_CANVAS_OBJECT_CLASS))
     {
        Evas_Coord x = 0, y = 0, w = 0, h = 0;
        evas_object_geometry_get(obj, &x, &y, &w, &h);
        if (efl_isa(obj, EFL_UI_WIN_CLASS)) x = y = 0;

        evas_object_polygon_point_add(rect, x, y);
        evas_object_polygon_point_add(rect, x + w, y);
        evas_object_polygon_point_add(rect, x + w, y + h);
        evas_object_polygon_point_add(rect, x, y + h);
     }
   else
     {
        Evas_Coord w = 0, h = 0;
        evas_output_size_get(obj, &w, &h);

        evas_object_polygon_point_add(rect, 0, 0);
        evas_object_polygon_point_add(rect, w, 0);
        evas_object_polygon_point_add(rect, w, h);
        evas_object_polygon_point_add(rect, 0, h);
     }

   /* Put the object as high as possible. */
   evas_object_layer_set(rect, EVAS_LAYER_MAX);
   evas_object_color_set(rect, HIGHLIGHT_R, HIGHLIGHT_G, HIGHLIGHT_B, HIGHLIGHT_A);
   evas_object_show(rect);

   /* Add Timer for fade and a callback to delete timer on obj del */
   Ecore_Animator *t = ecore_animator_add(_obj_highlight_fade, rect);
   evas_object_event_callback_add(rect, EVAS_CALLBACK_DEL, _obj_highlight_del, t);
   return EINA_DEBUG_OK;
}

EAPI Evas_Debug_Screenshot *
evas_debug_screenshot_decode(char *buffer, unsigned int size, uint64_t *obj)
{
   Evas_Debug_Screenshot *s = NULL;
   struct tm *t = NULL;
   int w, h;
   unsigned int hdr_size = sizeof(uint64_t) + sizeof(struct tm) + 2 * sizeof(int);
   if (size < hdr_size) return NULL;
   EXTRACT(buffer, obj, sizeof(uint64_t));
   t = (struct tm *)buffer;
   buffer += sizeof(struct tm);
   EXTRACT(buffer, &w, sizeof(int));
   EXTRACT(buffer, &h, sizeof(int));
   size -= hdr_size;
   if (size != (w * h * sizeof(int))) return NULL;

   s = calloc(1, sizeof(*s));
   s->w = w;
   s->h = h;
   memcpy(&s->time, t, sizeof(struct tm));
   s->img = malloc(size);
   memcpy(s->img, buffer, size);
   return s;
}

static Eina_Debug_Error
_win_screenshot_cb(Eina_Debug_Session *session, int srcid, void *buffer, int size)
{
   struct tm *t = NULL;
   time_t now = time(NULL);
   uint64_t ptr64 = 0;
   Ecore_Evas *ee = NULL;
   Ecore_X_Image *img;
   Ecore_X_Window_Attributes att;
   unsigned char *img_src;
   unsigned char *resp = NULL, *tmp;
   int bpl = 0, rows = 0, bpp = 0;
   int w, h;
   unsigned int hdr_size = sizeof(uint64_t) + sizeof(struct tm) + 2 * sizeof(int);

   if (size <= 0) return EINA_DEBUG_ERROR;
   memcpy(&ptr64, buffer, sizeof(ptr64));
   Eo *e = (Eo *)ptr64;
   if (!efl_isa(e, EVAS_CANVAS_CLASS)) goto end;

   ee = ecore_evas_ecore_evas_get(e);
   if (!ee) goto end;

   Ecore_X_Window win = (Ecore_X_Window) ecore_evas_window_get(ee);

   if (!win)
     {
        printf("Can't grab window.\n");
        goto end;
     }

   t = localtime(&now);
   t->tm_zone = NULL;

   memset(&att, 0, sizeof(Ecore_X_Window_Attributes));
   ecore_x_window_attributes_get(win, &att);
   w = att.w;
   h = att.h;
   img = ecore_x_image_new(w, h, att.visual, att.depth);
   ecore_x_image_get(img, win, 0, 0, 0, 0, w, h);
   img_src = ecore_x_image_data_get(img, &bpl, &rows, &bpp);
   resp = tmp = malloc(hdr_size + (w * h * sizeof(int)));
   STORE(tmp, &ptr64, sizeof(ptr64));
   STORE(tmp, t, sizeof(struct tm));
   STORE(tmp, &w, sizeof(int));
   STORE(tmp, &h, sizeof(int));
   if (!ecore_x_image_is_argb32_get(img))
     {  /* Fill resp buffer with image convert */
        ecore_x_image_to_argb_convert(img_src, bpp, bpl, att.colormap, att.visual,
              0, 0, w, h, (unsigned int *)tmp,
              (w * sizeof(int)), 0, 0);
     }
   else
     {  /* Fill resp buffer by copy */
        memcpy(tmp, img_src, (w * h * sizeof(int)));
     }

   /* resp now holds window bitmap */
   ecore_x_image_free(img);

   eina_debug_session_send(session, srcid, _win_screenshot_op, resp,
         hdr_size + (w * h * sizeof(int)));

end:
   if (resp) free(resp);
   return EINA_DEBUG_OK;
}

static const Eina_Debug_Opcode _debug_ops[] =
{
     {"Evas/object/highlight", &_obj_highlight_op, &_obj_highlight_cb},
     {"Evas/window/screenshot", &_win_screenshot_op, &_win_screenshot_cb},
     {NULL, NULL, NULL}
};

EAPI Eina_Bool
evas_debug_init(void)
{
   evas_init();

   eina_debug_opcodes_register(NULL, _debug_ops, NULL);

   printf("%s - In\n", __FUNCTION__);
   return EINA_TRUE;
}

EAPI Eina_Bool
evas_debug_shutdown(void)
{
   evas_shutdown();

   return EINA_TRUE;
}