Browse Source

add an option to set the preferred client icon size

_NET_WM_ICON contains a list of icons and until now, the first one was
picked without regard to it's size. This adds a global option to set
the preferred icon size. When getting the client icon, the best size
match is picked. The size can be set via
awesome.set_preferred_icon_size() and the default is 0, which will pick
the smallest non-zero size icon available.

Signed-off-by: Lukáš Hrázký <lukkash@email.cz>
Lukáš Hrázký 4 years ago
parent
commit
ea94f7f7e6
6 changed files with 55 additions and 16 deletions
  1. 3
    0
      awesome.c
  2. 32
    14
      ewmh.c
  3. 1
    1
      ewmh.h
  4. 2
    0
      globalconf.h
  5. 16
    0
      luaa.c
  6. 1
    1
      property.c

+ 3
- 0
awesome.c View File

@@ -543,6 +543,9 @@ main(int argc, char **argv)
543 543
     /* We have no clue where the input focus is right now */
544 544
     globalconf.focus.need_update = true;
545 545
 
546
+    /* set the default preferred icon size */
547
+    globalconf.preferred_icon_size = 0;
548
+
546 549
     /* XLib sucks */
547 550
     XkbIgnoreExtension(True);
548 551
 

+ 32
- 14
ewmh.c View File

@@ -662,27 +662,45 @@ ewmh_window_icon_get_unchecked(xcb_window_t w)
662 662
 }
663 663
 
664 664
 static cairo_surface_t *
665
-ewmh_window_icon_from_reply(xcb_get_property_reply_t *r)
665
+ewmh_window_icon_from_reply(xcb_get_property_reply_t *r, uint32_t preferred_size)
666 666
 {
667
-    uint32_t *data;
668
-    uint64_t len;
667
+    uint32_t *data, *end, *found_data = 0;
668
+    uint32_t found_size = 0;
669 669
 
670 670
     if(!r || r->type != XCB_ATOM_CARDINAL || r->format != 32 || r->length < 2)
671 671
         return 0;
672 672
 
673 673
     data = (uint32_t *) xcb_get_property_value(r);
674
-    if (!data)
675
-        return 0;
674
+    if (!data) return 0;
675
+
676
+    end = data + r->length;
676 677
 
677
-    /* Check that the property is as long as it should be, handling integer
678
-     * overflow. <uint32_t> times <another uint32_t casted to uint64_t> always
679
-     * fits into an uint64_t and thus this multiplication cannot overflow.
678
+    /* Goes over the icon data and picks the icon that best matches the size preference.
679
+     * In case the size match is not exact, picks the closest bigger size if present,
680
+     * closest smaller size otherwise.
680 681
      */
681
-    len = data[0] * (uint64_t) data[1];
682
-    if (!data[0] || !data[1] || len > r->length - 2)
683
-        return 0;
682
+    while (data + 1 < end) {
683
+        /* check whether the data size specified by width and height fits into the array we got */
684
+        uint64_t data_size = (uint64_t) data[0] * data[1];
685
+        if (data_size > (uint64_t) (end - data - 2)) break;
686
+
687
+        /* use the greater of the two dimensions to match against the preferred size */
688
+        uint32_t size = MAX(data[0], data[1]);
689
+        /* pick the icon if it's a better match than the one we already have */
690
+        if (data[0] && data[1] && (
691
+            (found_size < preferred_size && size > found_size) ||
692
+            (found_size > preferred_size && size >= preferred_size && size < found_size)))
693
+        {
694
+            found_data = data;
695
+            found_size = size;
696
+        }
697
+
698
+        data += data_size + 2;
699
+    }
700
+
701
+    if (!found_data) return 0;
684 702
 
685
-    return draw_surface_from_data(data[0], data[1], data + 2);
703
+    return draw_surface_from_data(found_data[0], found_data[1], found_data + 2);
686 704
 }
687 705
 
688 706
 /** Get NET_WM_ICON.
@@ -690,10 +708,10 @@ ewmh_window_icon_from_reply(xcb_get_property_reply_t *r)
690 708
  * \return The number of elements on stack.
691 709
  */
692 710
 cairo_surface_t *
693
-ewmh_window_icon_get_reply(xcb_get_property_cookie_t cookie)
711
+ewmh_window_icon_get_reply(xcb_get_property_cookie_t cookie, uint32_t preferred_size)
694 712
 {
695 713
     xcb_get_property_reply_t *r = xcb_get_property_reply(globalconf.connection, cookie, NULL);
696
-    cairo_surface_t *surface = ewmh_window_icon_from_reply(r);
714
+    cairo_surface_t *surface = ewmh_window_icon_from_reply(r, preferred_size);
697 715
     p_delete(&r);
698 716
     return surface;
699 717
 }

+ 1
- 1
ewmh.h View File

@@ -41,7 +41,7 @@ void ewmh_process_client_strut(client_t *);
41 41
 void ewmh_update_strut(xcb_window_t, strut_t *);
42 42
 void ewmh_update_window_type(xcb_window_t window, uint32_t type);
43 43
 xcb_get_property_cookie_t ewmh_window_icon_get_unchecked(xcb_window_t);
44
-cairo_surface_t *ewmh_window_icon_get_reply(xcb_get_property_cookie_t);
44
+cairo_surface_t *ewmh_window_icon_get_reply(xcb_get_property_cookie_t, uint32_t preferred_size);
45 45
 
46 46
 #endif
47 47
 // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80

+ 2
- 0
globalconf.h View File

@@ -167,6 +167,8 @@ typedef struct
167 167
     struct xkb_context *xkb_ctx;
168 168
     /* xkb state of dead keys on keyboard */
169 169
     struct xkb_state *xkb_state;
170
+    /** The preferred size of client icons for this screen */
171
+    uint32_t preferred_icon_size;
170 172
 } awesome_t;
171 173
 
172 174
 extern awesome_t globalconf;

+ 16
- 0
luaa.c View File

@@ -162,6 +162,21 @@ luaA_load_image(lua_State *L)
162 162
     return 1;
163 163
 }
164 164
 
165
+/** Set the preferred size for client icons.
166
+ *
167
+ * The closest equal or bigger size is picked if present, otherwise the closest
168
+ * smaller size is picked. The default is 0 pixels, ie. the smallest icon.
169
+ *
170
+ * @param size The size of the icons in pixels.
171
+ * @function set_preferred_icon_size
172
+ */
173
+static int
174
+luaA_set_preferred_icon_size(lua_State *L)
175
+{
176
+    globalconf.preferred_icon_size = luaL_checknumber(L, 1);
177
+    return 0;
178
+}
179
+
165 180
 /** UTF-8 aware string length computing.
166 181
  * \param L The Lua VM state.
167 182
  * \return The number of elements pushed on stack.
@@ -407,6 +422,7 @@ luaA_init(xdgHandle* xdg)
407 422
         { "emit_signal", luaA_awesome_emit_signal },
408 423
         { "systray", luaA_systray },
409 424
         { "load_image", luaA_load_image },
425
+        { "set_preferred_icon_size", luaA_set_preferred_icon_size },
410 426
         { "register_xproperty", luaA_register_xproperty },
411 427
         { "set_xproperty", luaA_set_xproperty },
412 428
         { "get_xproperty", luaA_get_xproperty },

+ 1
- 1
property.c View File

@@ -273,7 +273,7 @@ property_get_net_wm_icon(client_t *c)
273 273
 void
274 274
 property_update_net_wm_icon(client_t *c, xcb_get_property_cookie_t cookie)
275 275
 {
276
-    cairo_surface_t *surface = ewmh_window_icon_get_reply(cookie);
276
+    cairo_surface_t *surface = ewmh_window_icon_get_reply(cookie, globalconf.preferred_icon_size);
277 277
 
278 278
     if(!surface)
279 279
         return;

Loading…
Cancel
Save