summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorUli Schlachter <psychon@znc.in>2011-03-11 11:24:27 +0100
committerArnaud Fontaine <arnau@debian.org>2011-03-26 16:28:33 +0900
commitfa4118c9335a7ab4ad9dd9d0917ae02d97106e56 (patch)
treed73a6e80332b51f1cd748236b290f222eee5fdd4
parentc8a36b8591fe50b5fcea31d6bd5d469f8ac1c125 (diff)
downloadutil-wm-fa4118c9335a7ab4ad9dd9d0917ae02d97106e56.tar.gz
Return more icons from _NET_WM_ICON
EWMH says that _NET_WM_ICON is an array of icon. That means that it can contain more than one icon. This way, apps can provide icons of different sizes. Common sizes seem to be 16x16, 32x32 and 48x48. This commit makes it possible to access all the icons in _NET_WM_ICON via iterators instead of just the first one. Thanks to Arnaud Fontaine for his help with the API. Signed-off-by: Uli Schlachter <psychon@znc.in> Signed-off-by: Arnaud Fontaine <arnau@debian.org>
-rw-r--r--ewmh/ewmh.c.m477
-rw-r--r--ewmh/xcb_ewmh.h.m420
2 files changed, 87 insertions, 10 deletions
diff --git a/ewmh/ewmh.c.m4 b/ewmh/ewmh.c.m4
index 490727e..6f90814 100644
--- a/ewmh/ewmh.c.m4
+++ b/ewmh/ewmh.c.m4
@@ -1146,21 +1146,31 @@ xcb_ewmh_get_wm_icon_from_reply(xcb_ewmh_get_wm_icon_reply_t *wm_icon,
{
if(!r || r->type != XCB_ATOM_CARDINAL || r->format != 32)
return 0;
+
uint32_t r_value_len = xcb_get_property_value_length(r);
uint32_t *r_value = (uint32_t *) xcb_get_property_value(r);
- if(r_value_len <= (sizeof(uint32_t) * 2) || !r_value)
- return 0;
- /* Check that the property is as long as it should be, handling
- integer overflow. "-2" to handle the width and height fields. */
- const uint64_t expected_len = r_value[0] * (uint64_t) r_value[1];
- if(!r_value[0] || !r_value[1] || expected_len > r_value_len / 4 - 2)
+ /* Find the number of icons in the reply. */
+ while(r_value_len > (sizeof(uint32_t) * 2) && r_value && r_value[0] && r_value[1])
+ {
+ /* Check that the property is as long as it should be (in bytes),
+ handling integer overflow. "+2" to handle the width and height
+ fields. */
+ const uint64_t expected_len = (r_value[0] * (uint64_t) r_value[1] + 2) * 4;
+ if(expected_len > r_value_len)
+ break;
+
+ wm_icon->num_icons++;
+
+ /* Find pointer to next icon in the reply. */
+ r_value_len -= expected_len;
+ r_value = (uint32_t *) (((uint8_t *) r_value) + expected_len);
+ }
+
+ if(!wm_icon->num_icons)
return 0;
wm_icon->_reply = r;
- wm_icon->width = r_value[0];
- wm_icon->height = r_value[1];
- wm_icon->data = r_value + 2;
return 1;
}
@@ -1185,6 +1195,55 @@ xcb_ewmh_get_wm_icon_reply_wipe(xcb_ewmh_get_wm_icon_reply_t *wm_icon)
free(wm_icon->_reply);
}
+xcb_ewmh_wm_icon_iterator_t
+xcb_ewmh_get_wm_icon_iterator(const xcb_ewmh_get_wm_icon_reply_t *wm_icon)
+{
+ xcb_ewmh_wm_icon_iterator_t ret;
+
+ ret.width = 0;
+ ret.height = 0;
+ ret.data = NULL;
+ ret.rem = wm_icon->num_icons;
+ ret.index = 0;
+
+ if(ret.rem > 0)
+ {
+ uint32_t *r_value = (uint32_t *) xcb_get_property_value(wm_icon->_reply);
+ ret.width = r_value[0];
+ ret.height = r_value[1];
+ ret.data = &r_value[2];
+ }
+
+ return ret;
+}
+
+unsigned int xcb_ewmh_get_wm_icon_length(const xcb_ewmh_get_wm_icon_reply_t *wm_icon)
+{
+ return wm_icon->num_icons;
+}
+
+void xcb_ewmh_get_wm_icon_next(xcb_ewmh_wm_icon_iterator_t *iterator)
+{
+ if(iterator->rem <= 1)
+ {
+ iterator->index += iterator->rem;
+ iterator->rem = 0;
+ iterator->width = 0;
+ iterator->height = 0;
+ iterator->data = NULL;
+ return;
+ }
+
+ uint64_t icon_len = iterator->width * (uint64_t) iterator->height;
+ uint32_t *data = iterator->data + icon_len;
+
+ iterator->rem--;
+ iterator->index++;
+ iterator->width = data[0];
+ iterator->height = data[1];
+ iterator->data = &data[2];
+}
+
/**
* _NET_WM_PID
*/
diff --git a/ewmh/xcb_ewmh.h.m4 b/ewmh/xcb_ewmh.h.m4
index c1d8f09..048d020 100644
--- a/ewmh/xcb_ewmh.h.m4
+++ b/ewmh/xcb_ewmh.h.m4
@@ -295,7 +295,7 @@ typedef struct {
} xcb_ewmh_wm_strut_partial_t;
/**
- * @brief Hold reply of _NET_WM_ICON GetProperty
+ * @brief Hold a single icon from reply of _NET_WM_ICON GetProperty
*/
typedef struct {
/** Icon width */
@@ -304,6 +304,18 @@ typedef struct {
uint32_t height;
/** Rows, left to right and top to bottom of the CARDINAL ARGB */
uint32_t *data;
+ /** Number of icons remaining */
+ unsigned int rem;
+ /** Index of the current icon in the array of icons */
+ unsigned int index;
+} xcb_ewmh_wm_icon_iterator_t;
+
+/**
+ * @brief Hold reply of _NET_WM_ICON GetProperty
+ */
+typedef struct {
+ /** Number of icons */
+ unsigned int num_icons;
/** The actual GetProperty reply */
xcb_get_property_reply_t *_reply;
} xcb_ewmh_get_wm_icon_reply_t;
@@ -2023,6 +2035,12 @@ uint8_t xcb_ewmh_get_wm_icon_reply(xcb_ewmh_connection_t *ewmh,
xcb_ewmh_get_wm_icon_reply_t *wm_icon,
xcb_generic_error_t **e);
+xcb_ewmh_wm_icon_iterator_t xcb_ewmh_get_wm_icon_iterator(const xcb_ewmh_get_wm_icon_reply_t *wm_icon);
+
+unsigned int xcb_ewmh_get_wm_icon_length(const xcb_ewmh_get_wm_icon_reply_t *wm_icon);
+
+void xcb_ewmh_get_wm_icon_next(xcb_ewmh_wm_icon_iterator_t *iterator);
+
void xcb_ewmh_get_wm_icon_reply_wipe(xcb_ewmh_get_wm_icon_reply_t *wm_icon);
xcb_void_cookie_t xcb_ewmh_set_wm_pid(xcb_ewmh_connection_t *ewmh,