diff --git a/lib/naughty/dbus.lua.in b/lib/naughty/dbus.lua.in index 4823c801..98113412 100644 --- a/lib/naughty/dbus.lua.in +++ b/lib/naughty/dbus.lua.in @@ -60,6 +60,43 @@ local function sendNotificationClosed(notificationId, reason) "i", reason) end +local function convert_icon(w, h, rowstride, channels, data) + -- Do the arguments look sane? (e.g. we have enough data) + local expected_length = rowstride * (h - 1) + w * channels + if w < 0 or h < 0 or rowstride < 0 or (channels ~= 3 and channels ~= 4) or + string.len(data) < expected_length then + w = 0 + h = 0 + end + + local format = cairo.Format[channels == 4 and 'ARGB32' or 'RGB24'] + + -- Figure out some stride magic (cairo dictates rowstride) + local stride = cairo.Format.stride_for_width(format, w) + local append = schar(0):rep(stride - 4 * w) + local offset = 0 + + -- Now convert each row on its own + local rows = {} + + for y = 1, h do + local this_row = {} + + for i = 1 + offset, w * channels + offset, channels do + local R, G, B, A = sbyte(data, i, i + channels - 1) + tins(this_row, schar(B, G, R, A or 255)) + end + + -- Handle rowstride, offset is stride for the input, append for output + tins(this_row, append) + tins(rows, tcat(this_row)) + + offset = offset + rowstride + end + + return cairo.ImageSurface.create_for_data(tcat(rows), format, w, h, stride) +end + capi.dbus.connect_signal("org.freedesktop.Notifications", function (data, appname, replaces_id, icon, title, text, actions, hints, expire) local args = { } if data.member == "Notify" then @@ -131,42 +168,7 @@ capi.dbus.connect_signal("org.freedesktop.Notifications", function (data, appnam -- 6 -> channels -- 7 -> data local w, h, rowstride, _, _, channels, data = unpack(hints.icon_data) - - -- Do the arguments look sane? (e.g. we have enough data) - local expected_length = rowstride * (h - 1) + w * channels - if w < 0 or h < 0 or rowstride < 0 or (channels ~= 3 and channels ~= 4) or - string.len(data) < expected_length then - w = 0 - h = 0 - end - - local format = cairo.Format[channels == 4 and 'ARGB32' or 'RGB24'] - - -- Figure out some stride magic (cairo dictates rowstride) - local stride = cairo.Format.stride_for_width(format, w) - local append = schar(0):rep(stride - 4 * w) - local offset = 0 - - -- Now convert each row on its own - local rows = {} - - for y = 1, h do - local this_row = {} - - for i = 1 + offset, w * channels + offset, channels do - local R, G, B, A = sbyte(data, i, i + channels - 1) - tins(this_row, schar(B, G, R, A or 255)) - end - - -- Handle rowstride, offset is stride for the input, append for output - tins(this_row, append) - tins(rows, tcat(this_row)) - - offset = offset + rowstride - end - - args.icon = cairo.ImageSurface.create_for_data(tcat(rows), format, - w, h, stride) + args.icon = convert_icon(w, h, rowstride, channels, data) end if replaces_id and replaces_id ~= "" and replaces_id ~= 0 then args.replaces_id = replaces_id