[PATCH 1/2] xwm: Choose icon closest to target size
Scott Moreau
oreaus at gmail.com
Thu Mar 22 02:59:42 UTC 2018
Xwayland clients can offer multiple icon sizes in no particular order.
Previously xwm was selecting the first one unconditionally. This patch
selects the icon that matches the size closest to the target size. The
target size is hard coded to 16 since there is only one theme and the
data used to create the theme is hard coded.
---
xwayland/window-manager.c | 66 ++++++++++++++++++++++++++++++++++++++++++-----
1 file changed, 60 insertions(+), 6 deletions(-)
diff --git a/xwayland/window-manager.c b/xwayland/window-manager.c
index c307e19..8b7d2f6 100644
--- a/xwayland/window-manager.c
+++ b/xwayland/window-manager.c
@@ -1352,6 +1352,63 @@ weston_wm_window_schedule_repaint(struct weston_wm_window *window)
weston_wm_window_do_repaint, window);
}
+static uint32_t *
+get_icon_size_from_data(int target_width, int target_height,
+ uint32_t *width, uint32_t *height,
+ uint32_t length, uint32_t *data)
+{
+ uint32_t *d = data, **img = NULL, *ret = NULL, w, h;
+ int num_sizes = 0, *sizes = NULL, a1, a2, a3;
+
+ *width = *height = 0;
+
+ while (d - data < length / 4) {
+ w = *d++;
+ h = *d++;
+
+ sizes = realloc(sizes, 2 * (num_sizes + 1) * sizeof(uint32_t));
+ if (!sizes) {
+ free(img);
+ return NULL;
+ }
+
+ img = realloc(img, (num_sizes + 1) * sizeof(uint32_t *));
+ if (!img) {
+ free(sizes);
+ return NULL;
+ }
+
+ sizes[(num_sizes * 2) + 0] = w;
+ sizes[(num_sizes * 2) + 1] = h;
+ img[num_sizes] = d;
+
+ num_sizes++;
+ d += w * h;
+ }
+
+ /* Choose closest match by comparing icon dimension areas */
+ a1 = target_width * target_height;
+
+ while (num_sizes--) {
+ w = sizes[(num_sizes * 2) + 0];
+ h = sizes[(num_sizes * 2) + 1];
+
+ a2 = w * h;
+ a3 = *width * *height;
+
+ if (a2 != a3 && abs(a2 - a1) < abs(a3 - a1)) {
+ *width = w;
+ *height = w;
+ ret = img[num_sizes];
+ }
+ }
+
+ free(sizes);
+ free(img);
+
+ return ret;
+}
+
static void
weston_wm_handle_icon(struct weston_wm *wm, struct weston_wm_window *window)
{
@@ -1361,9 +1418,6 @@ weston_wm_handle_icon(struct weston_wm *wm, struct weston_wm_window *window)
uint32_t *data, width, height;
cairo_surface_t *new_surface;
- /* TODO: icons don’t have any specified order, we should pick the
- * closest one to the target dimension instead of the first one. */
-
cookie = xcb_get_property(wm->conn, 0, window->id,
wm->atom.net_wm_icon, XCB_ATOM_ANY, 0,
UINT32_MAX);
@@ -1375,11 +1429,11 @@ weston_wm_handle_icon(struct weston_wm *wm, struct weston_wm_window *window)
return;
data = xcb_get_property_value(reply);
- width = *data++;
- height = *data++;
+
+ data = get_icon_size_from_data(16, 16, &width, &height, length, data);
/* Some checks against malformed input. */
- if (width == 0 || height == 0 || length < 2 + width * height)
+ if (!data || width == 0 || height == 0 || length < 2 + width * height)
return;
new_surface =
--
2.7.4
More information about the wayland-devel
mailing list