Browse Source

Don't pass cairo surfaces around on the lua stack

Now that the C code uses lightuserdata for passing around cairo surfaces, they
are no longer automatically garbage collected. To avoid memleaks, this commit
compares the C code to use cairo_surface_t pointers instead of the lua stack.

This also fixes a memleak were a client's icon was leaked.

Signed-off-by: Uli Schlachter <psychon@znc.in>
Uli Schlachter 7 years ago
parent
commit
e57af377bb
8 changed files with 49 additions and 43 deletions
  1. 7
    10
      draw.c
  2. 2
    2
      draw.h
  3. 5
    5
      ewmh.c
  4. 3
    1
      ewmh.h
  5. 6
    1
      luaa.c
  6. 20
    14
      objects/client.c
  7. 1
    1
      objects/client.h
  8. 5
    9
      property.c

+ 7
- 10
draw.c View File

@@ -105,8 +105,8 @@ free_data(void *data)
105 105
  * \param data The image's data in ARGB format, will be copied by this function.
106 106
  * \return Number of items pushed on the lua stack.
107 107
  */
108
-int
109
-luaA_surface_from_data(lua_State *L, int width, int height, uint32_t *data)
108
+cairo_surface_t *
109
+draw_surface_from_data(int width, int height, uint32_t *data)
110 110
 {
111 111
     unsigned long int len = width * height;
112 112
     unsigned long int i;
@@ -133,10 +133,7 @@ luaA_surface_from_data(lua_State *L, int width, int height, uint32_t *data)
133 133
     /* This makes sure that buffer will be freed */
134 134
     cairo_surface_set_user_data(surface, &data_key, buffer, &free_data);
135 135
 
136
-    /* lua has to make sure to free the ref or we have a leak */
137
-    lua_pushlightuserdata(L, surface);
138
-
139
-    return 1;
136
+    return surface;
140 137
 }
141 138
 
142 139
 /** Duplicate the specified image surface.
@@ -205,21 +202,21 @@ image_imlib_load_strerror(Imlib_Load_Error e)
205 202
  * \param path file to load
206 203
  * \return A cairo image surface or NULL on error.
207 204
  */
208
-int
205
+cairo_surface_t *
209 206
 draw_load_image(lua_State *L, const char *path)
210 207
 {
211 208
     Imlib_Image imimage;
212 209
     Imlib_Load_Error e = IMLIB_LOAD_ERROR_NONE;
213
-    int ret;
210
+    cairo_surface_t *ret;
214 211
 
215 212
     imimage = imlib_load_image_with_error_return(path, &e);
216 213
     if (!imimage) {
217 214
         luaL_error(L, "Cannot load image '%s': %s", path, image_imlib_load_strerror(e));
218
-        return 0;
215
+        return NULL;
219 216
     }
220 217
 
221 218
     imlib_context_set_image(imimage);
222
-    ret = luaA_surface_from_data(L, imlib_image_get_width(),
219
+    ret = draw_surface_from_data(imlib_image_get_width(),
223 220
             imlib_image_get_height(), imlib_image_get_data_for_reading_only());
224 221
     imlib_free_image_and_decache();
225 222
     return ret;

+ 2
- 2
draw.h View File

@@ -65,9 +65,9 @@ a_iso2utf8(const char *str, ssize_t len, char **dest, ssize_t *dlen)
65 65
     return false;
66 66
 }
67 67
 
68
-int luaA_surface_from_data(lua_State *L, int width, int height, uint32_t *data);
68
+cairo_surface_t *draw_surface_from_data(int width, int height, uint32_t *data);
69 69
 cairo_surface_t *draw_dup_image_surface(cairo_surface_t *surface);
70
-int draw_load_image(lua_State *L, const char *path);
70
+cairo_surface_t *draw_load_image(lua_State *L, const char *path);
71 71
 
72 72
 #endif
73 73
 // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80

+ 5
- 5
ewmh.c View File

@@ -634,7 +634,7 @@ ewmh_window_icon_get_unchecked(xcb_window_t w)
634 634
                                     _NET_WM_ICON, XCB_ATOM_CARDINAL, 0, UINT32_MAX);
635 635
 }
636 636
 
637
-static int
637
+static cairo_surface_t *
638 638
 ewmh_window_icon_from_reply(xcb_get_property_reply_t *r)
639 639
 {
640 640
     uint32_t *data;
@@ -655,20 +655,20 @@ ewmh_window_icon_from_reply(xcb_get_property_reply_t *r)
655 655
     if (!data[0] || !data[1] || len > r->length - 2)
656 656
         return 0;
657 657
 
658
-    return luaA_surface_from_data(globalconf.L, data[0], data[1], data + 2);
658
+    return draw_surface_from_data(data[0], data[1], data + 2);
659 659
 }
660 660
 
661 661
 /** Get NET_WM_ICON.
662 662
  * \param cookie The cookie.
663 663
  * \return The number of elements on stack.
664 664
  */
665
-int
665
+cairo_surface_t *
666 666
 ewmh_window_icon_get_reply(xcb_get_property_cookie_t cookie)
667 667
 {
668 668
     xcb_get_property_reply_t *r = xcb_get_property_reply(globalconf.connection, cookie, NULL);
669
-    int ret = ewmh_window_icon_from_reply(r);
669
+    cairo_surface_t *surface = ewmh_window_icon_from_reply(r);
670 670
     p_delete(&r);
671
-    return ret;
671
+    return surface;
672 672
 }
673 673
 
674 674
 // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80

+ 3
- 1
ewmh.h View File

@@ -22,6 +22,8 @@
22 22
 #ifndef AWESOME_EWMH_H
23 23
 #define AWESOME_EWMH_H
24 24
 
25
+#include <cairo.h>
26
+
25 27
 #include "globalconf.h"
26 28
 #include "strut.h"
27 29
 
@@ -37,7 +39,7 @@ void ewmh_process_client_strut(client_t *);
37 39
 void ewmh_update_strut(xcb_window_t, strut_t *);
38 40
 void ewmh_update_window_type(xcb_window_t window, uint32_t type);
39 41
 xcb_get_property_cookie_t ewmh_window_icon_get_unchecked(xcb_window_t);
40
-int ewmh_window_icon_get_reply(xcb_get_property_cookie_t);
42
+cairo_surface_t *ewmh_window_icon_get_reply(xcb_get_property_cookie_t);
41 43
 
42 44
 #endif
43 45
 // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80

+ 6
- 1
luaa.c View File

@@ -109,7 +109,12 @@ static int
109 109
 luaA_load_image(lua_State *L)
110 110
 {
111 111
     const char *filename = luaL_checkstring(L, 1);
112
-    return draw_load_image(L, filename);
112
+    cairo_surface_t *surface = draw_load_image(L, filename);
113
+    if (!surface)
114
+        return 0;
115
+    /* lua has to make sure to free the ref or we have a leak */
116
+    lua_pushlightuserdata(L, surface);
117
+    return 1;
113 118
 }
114 119
 
115 120
 /** UTF-8 aware string length computing.

+ 20
- 14
objects/client.c View File

@@ -1040,19 +1040,17 @@ luaA_client_isvisible(lua_State *L)
1040 1040
  * \param iidx The image index on the stack.
1041 1041
  */
1042 1042
 void
1043
-client_set_icon(lua_State *L, int cidx, int iidx)
1043
+client_set_icon(client_t *c, cairo_surface_t *s)
1044 1044
 {
1045
-    client_t *c = luaA_checkudata(L, cidx, &client_class);
1046
-    cairo_surface_t *surf = NULL;
1047
-    if(!lua_isnil(L, iidx))
1048
-    {
1049
-        cairo_surface_t **cairo_surface = (cairo_surface_t **)lua_touserdata(L, iidx);
1050
-        surf = draw_dup_image_surface(*cairo_surface);
1051
-    }
1045
+    if (s)
1046
+        s = draw_dup_image_surface(s);
1052 1047
     if(c->icon)
1053 1048
         cairo_surface_destroy(c->icon);
1054
-    c->icon = surf;
1055
-    luaA_object_emit_signal(L, cidx < iidx ? cidx : cidx - 1, "property::icon", 0);
1049
+    c->icon = s;
1050
+
1051
+    luaA_object_push(globalconf.L, c);
1052
+    luaA_object_emit_signal(globalconf.L, -1, "property::icon", 0);
1053
+    lua_pop(globalconf.L, 1);
1056 1054
 }
1057 1055
 
1058 1056
 /** Kill a client.
@@ -1294,7 +1292,10 @@ luaA_client_set_maximized_vertical(lua_State *L, client_t *c)
1294 1292
 static int
1295 1293
 luaA_client_set_icon(lua_State *L, client_t *c)
1296 1294
 {
1297
-    client_set_icon(L, -3, -1);
1295
+    cairo_surface_t *surf = NULL;
1296
+    if(!lua_isnil(L, -1))
1297
+        surf = (cairo_surface_t *)lua_touserdata(L, -1);
1298
+    client_set_icon(c, surf);
1298 1299
     return 0;
1299 1300
 }
1300 1301
 
@@ -1393,7 +1394,7 @@ luaA_client_get_content(lua_State *L, client_t *c)
1393 1394
                                         c->geometry.width,
1394 1395
                                         c->geometry.height,
1395 1396
                                         ~0, XCB_IMAGE_FORMAT_Z_PIXMAP);
1396
-    int retval = 0;
1397
+    cairo_surface_t *surface = NULL;
1397 1398
 
1398 1399
     if(ximage)
1399 1400
     {
@@ -1408,13 +1409,18 @@ luaA_client_get_content(lua_State *L, client_t *c)
1408 1409
                     data[y * ximage->width + x] |= 0xff000000; /* set alpha to 0xff */
1409 1410
                 }
1410 1411
 
1411
-            retval = luaA_surface_from_data(L, ximage->width, ximage->height, data);
1412
+            surface = draw_surface_from_data(ximage->width, ximage->height, data);
1412 1413
             p_delete(&data);
1413 1414
         }
1414 1415
         xcb_image_destroy(ximage);
1415 1416
     }
1416 1417
 
1417
-    return retval;
1418
+    if (!surface)
1419
+        return 0;
1420
+
1421
+    /* lua has to make sure to free the ref or we have a leak */
1422
+    lua_pushlightuserdata(L, surface);
1423
+    return 1;
1418 1424
 }
1419 1425
 
1420 1426
 static int

+ 1
- 1
objects/client.h View File

@@ -142,7 +142,7 @@ void client_set_transient_for(lua_State *L, int, client_t *);
142 142
 void client_set_name(lua_State *L, int, char *);
143 143
 void client_set_alt_name(lua_State *L, int, char *);
144 144
 void client_set_group_window(lua_State *, int, xcb_window_t);
145
-void client_set_icon(lua_State *, int, int);
145
+void client_set_icon(client_t *c, cairo_surface_t *s);
146 146
 void client_set_skip_taskbar(lua_State *, int, bool);
147 147
 void client_focus(client_t *);
148 148
 void client_focus_update(client_t *);

+ 5
- 9
property.c View File

@@ -241,17 +241,13 @@ property_get_net_wm_icon(client_t *c)
241 241
 void
242 242
 property_update_net_wm_icon(client_t *c, xcb_get_property_cookie_t cookie)
243 243
 {
244
-    luaA_object_push(globalconf.L, c);
244
+    cairo_surface_t *surface = ewmh_window_icon_get_reply(cookie);
245 245
 
246
-    if(ewmh_window_icon_get_reply(cookie))
247
-    {
248
-        client_set_icon(globalconf.L, -2, -1);
249
-        /* remove icon */
250
-        lua_pop(globalconf.L, 1);
251
-    }
246
+    if(!surface)
247
+        return;
252 248
 
253
-    /* remove client */
254
-    lua_pop(globalconf.L, 1);
249
+    client_set_icon(c, surface);
250
+    cairo_surface_destroy(surface);
255 251
 }
256 252
 
257 253
 xcb_get_property_cookie_t

Loading…
Cancel
Save