i3 - improved tiling WM


Add configuration options for tray icon size and minimum panel size

Patch status: needinfo

Patch by Jaroslav Smid

To apply this patch, use:
curl http://cr.i3wm.org/patch/399/raw.patch | git am

b/i3bar/include/config.h

21
@@ -23,6 +23,8 @@ typedef enum { M_DOCK = 0, M_HIDE = 1, M_INVISIBLE = 2 } bar_display_mode_t;
22
 typedef struct config_t {
23
     int          modifier;
24
     position_t   position;
25
+    int          min_height;
26
+    int          tray_icon_size;
27
     int          verbose;
28
     struct xcb_color_strings_t colors;
29
     bool         disable_binding_mode_indicator;

b/i3bar/src/config.c

34
@@ -210,10 +210,42 @@ static int config_boolean_cb(void *params_, int val) {
35
     return 0;
36
 }
37
 
38
+/* Parse an integer value */
39
+#if YAJL_MAJOR >= 2
40
+static int config_integer_cb(void *params_, long long val) {
41
+#else
42
+static int config_integer_cb(void *params_, long val) {
43
+#endif
44
+    /* Minimum panel height, allowed values <0, INT16_MAX> */
45
+    if (!strcmp(cur_key, "min_height")) {
46
+        if (val < 0)
47
+            config.min_height = 0;
48
+        else if (val > INT16_MAX)
49
+            config.min_height = INT16_MAX;
50
+        else
51
+            config.min_height = (int)val;
52
+        return 1;
53
+    }
54
+
55
+    /* Tray icon size, allowed values <0, INT16_MAX> */
56
+    if (!strcmp(cur_key, "tray_icon_size")) {
57
+        if (val < 0)
58
+            config.tray_icon_size = 0;
59
+        else if (val > INT16_MAX)
60
+            config.tray_icon_size = INT16_MAX;
61
+        else
62
+            config.tray_icon_size = (int)val;
63
+        return 1;
64
+    }
65
+
66
+    return 0;
67
+}
68
+
69
 /* A datastructure to pass all these callbacks to yajl */
70
 static yajl_callbacks outputs_callbacks = {
71
     .yajl_null = config_null_cb,
72
     .yajl_boolean = config_boolean_cb,
73
+    .yajl_integer = config_integer_cb,
74
     .yajl_string = config_string_cb,
75
     .yajl_map_key = config_map_key_cb,
76
 };

b/i3bar/src/xcb.c

81
@@ -59,9 +59,12 @@ xcb_connection_t *conn;
82
 /* The font we'll use */
83
 static i3Font font;
84
 
85
-/* Overall height of the bar (based on font size) */
86
+/* Overall height of the bar */
87
 int bar_height;
88
 
89
+/* Pixel size of a tray icon */
90
+int tray_icon_size;
91
+
92
 /* These are only relevant for XKB, which we only need for grabbing modifiers */
93
 Display          *xkb_dpy;
94
 int              xkb_event_base;
95
@@ -372,7 +375,7 @@ void handle_button(xcb_button_press_event_t *event) {
96
                 TAILQ_FOREACH_REVERSE(trayclient, walk->trayclients, tc_head, tailq) {
97
                     if (!trayclient->mapped)
98
                         continue;
99
-                    tray_width += (font.height + 2);
100
+                    tray_width += (tray_icon_size + 2);
101
                 }
102
 
103
                 int block_x = 0, last_block_x;
104
@@ -452,8 +455,8 @@ static void configure_trayclients(void) {
105
             clients++;
106
 
107
             DLOG("Configuring tray window %08x to x=%d\n",
108
-                 trayclient->win, output->rect.w - (clients * (font.height + 2)));
109
-            uint32_t x = output->rect.w - (clients * (font.height + 2));
110
+                 trayclient->win, output->rect.w - (clients * (tray_icon_size + 2)));
111
+            uint32_t x = output->rect.w - (clients * (tray_icon_size + 2));
112
             xcb_configure_window(xcb_connection,
113
                                  trayclient->win,
114
                                  XCB_CONFIG_WINDOW_X,
115
@@ -563,16 +566,16 @@ static void handle_client_message(xcb_client_message_event_t* event) {
116
             xcb_reparent_window(xcb_connection,
117
                                 client,
118
                                 output->bar,
119
-                                output->rect.w - font.height - 2,
120
-                                2);
121
+                                output->rect.w - tray_icon_size - 2,
122
+                                (bar_height - tray_icon_size)/2);
123
             /* We reconfigure the window to use a reasonable size. The systray
124
              * specification explicitly says:
125
              *   Tray icons may be assigned any size by the system tray, and
126
              *   should do their best to cope with any size effectively
127
              */
128
             mask = XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT;
129
-            values[0] = font.height;
130
-            values[1] = font.height;
131
+            values[0] = tray_icon_size;
132
+            values[1] = tray_icon_size;
133
             xcb_configure_window(xcb_connection,
134
                                  client,
135
                                  mask,
136
@@ -802,10 +805,10 @@ static void handle_configure_request(xcb_configure_request_event_t *event) {
137
                 continue;
138
 
139
             xcb_rectangle_t rect;
140
-            rect.x = output->rect.w - (clients * (font.height + 2));
141
-            rect.y = 2;
142
-            rect.width = font.height;
143
-            rect.height = font.height;
144
+            rect.x = output->rect.w - (clients * (tray_icon_size + 2));
145
+            rect.y = (bar_height - tray_icon_size)/2;
146
+            rect.width = tray_icon_size;
147
+            rect.height = tray_icon_size;
148
 
149
             DLOG("This is a tray window. x = %d\n", rect.x);
150
             fake_configure_notify(xcb_connection, rect, event->window, 0);
151
@@ -1107,7 +1110,19 @@ void init_xcb_late(char *fontname) {
152
     font = load_font(fontname, true);
153
     set_font(&font);
154
     DLOG("Calculated Font-height: %d\n", font.height);
155
-    bar_height = font.height + 6;
156
+
157
+    bar_height = MAX(font.height + 6,
158
+                     config.min_height);
159
+
160
+    if (config.tray_icon_size != 0) {
161
+        /* Tray icon size is set. Increase bar's height if it won't fit */
162
+        tray_icon_size = config.tray_icon_size;
163
+        bar_height = MAX(tray_icon_size, bar_height);
164
+    }
165
+    else {
166
+        /* Tray icon size is not set. Use the same as font's height */
167
+        tray_icon_size = font.height;
168
+    }
169
 
170
     xcb_flush(xcb_connection);
171
 
172
@@ -1705,10 +1720,8 @@ void draw_bars(bool unhide) {
173
             TAILQ_FOREACH(trayclient, outputs_walk->trayclients, tailq) {
174
                 if (!trayclient->mapped)
175
                     continue;
176
-                /* We assume the tray icons are quadratic (we use the font
177
-                 * *height* as *width* of the icons) because we configured them
178
-                 * like this. */
179
-                traypx += font.height + 2;
180
+                /* We assume the tray icons are quadratic */
181
+                traypx += tray_icon_size + 2;
182
             }
183
             /* Add 2px of padding if there are any tray icons */
184
             if (traypx > 0)
185
@@ -1717,9 +1730,12 @@ void draw_bars(bool unhide) {
186
                           statusline_pm,
187
                           outputs_walk->buffer,
188
                           outputs_walk->bargc,
189
-                          MAX(0, (int16_t)(statusline_width - outputs_walk->rect.w + 4)), 0,
190
-                          MAX(0, (int16_t)(outputs_walk->rect.w - statusline_width - traypx - 4)), 3,
191
-                          MIN(outputs_walk->rect.w - traypx - 4, (int)statusline_width), font.height + 2);
192
+                          MAX(0, (int16_t)(statusline_width - outputs_walk->rect.w + 4)),
193
+                          0,
194
+                          MAX(0, (int16_t)(outputs_walk->rect.w - statusline_width - traypx - 4)),
195
+                          (bar_height - font.height - 2)/2,
196
+                          MIN(outputs_walk->rect.w - traypx - 4, (int)statusline_width),
197
+                          font.height + 2);
198
         }
199
 
200
         if (!config.disable_ws) {
201
@@ -1754,7 +1770,7 @@ void draw_bars(bool unhide) {
202
                               outputs_walk->bargc,
203
                               mask,
204
                               vals_border);
205
-                xcb_rectangle_t rect_border = { i, 1, ws_walk->name_width + 10, font.height + 4 };
206
+                xcb_rectangle_t rect_border = { i, 1, ws_walk->name_width + 10, bar_height - 2 };
207
                 xcb_poly_fill_rectangle(xcb_connection,
208
                                         outputs_walk->buffer,
209
                                         outputs_walk->bargc,
210
@@ -1765,7 +1781,7 @@ void draw_bars(bool unhide) {
211
                               outputs_walk->bargc,
212
                               mask,
213
                               vals);
214
-                xcb_rectangle_t rect = { i + 1, 2, ws_walk->name_width + 8, font.height + 2 };
215
+                xcb_rectangle_t rect = { i + 1, 2, ws_walk->name_width + 8, bar_height - 4 };
216
                 xcb_poly_fill_rectangle(xcb_connection,
217
                                         outputs_walk->buffer,
218
                                         outputs_walk->bargc,
219
@@ -1773,7 +1789,7 @@ void draw_bars(bool unhide) {
220
                                         &rect);
221
                 set_font_colors(outputs_walk->bargc, fg_color, bg_color);
222
                 draw_text(ws_walk->name, outputs_walk->buffer, outputs_walk->bargc,
223
-                          i + 5, 3, ws_walk->name_width);
224
+                          i + 5, (bar_height - font.height)/2, ws_walk->name_width);
225
                 i += 10 + ws_walk->name_width + 1;
226
 
227
             }

b/include/config.h

232
@@ -224,6 +224,12 @@ struct Barconfig {
233
      * disables the tray (it’s enabled by default). */
234
     char *tray_output;
235
 
236
+    /** Minimum height of the panel in pixels */
237
+    int min_height;
238
+
239
+    /** Size of tray icons in pixels */
240
+    int tray_icon_size;
241
+
242
     /** Path to the i3 IPC socket. This option is discouraged since programs
243
      * can find out the path by looking for the I3_SOCKET_PATH property on the
244
      * root window! */

b/include/config_directives.h

249
@@ -77,6 +77,8 @@ CFGFUN(bar_i3bar_command, const char *i3bar_command);
250
 CFGFUN(bar_color, const char *colorclass, const char *border, const char *background, const char *text);
251
 CFGFUN(bar_socket_path, const char *socket_path);
252
 CFGFUN(bar_tray_output, const char *output);
253
+CFGFUN(bar_tray_icon_size, const long size);
254
+CFGFUN(bar_min_height, const long size);
255
 CFGFUN(bar_color_single, const char *colorclass, const char *color);
256
 CFGFUN(bar_status_command, const char *command);
257
 CFGFUN(bar_binding_mode_indicator, const char *value);

b/parser-specs/config.spec

262
@@ -355,6 +355,8 @@ state BAR:
263
   'position'               -> BAR_POSITION
264
   'output'                 -> BAR_OUTPUT
265
   'tray_output'            -> BAR_TRAY_OUTPUT
266
+  'tray_icon_size'         -> BAR_TRAY_ICON_SIZE
267
+  'min_height'             -> BAR_MIN_HEIGHT
268
   'font'                   -> BAR_FONT
269
   'binding_mode_indicator' -> BAR_BINDING_MODE_INDICATOR
270
   'workspace_buttons'      -> BAR_WORKSPACE_BUTTONS
271
@@ -408,6 +410,14 @@ state BAR_TRAY_OUTPUT:
272
   output = string
273
       -> call cfg_bar_tray_output($output); BAR
274
 
275
+state BAR_TRAY_ICON_SIZE:
276
+  tray_icon_size = number
277
+              -> call cfg_bar_tray_icon_size(&tray_icon_size); BAR
278
+
279
+state BAR_MIN_HEIGHT:
280
+  min_height = number
281
+          -> call cfg_bar_min_height(&min_height); BAR
282
+
283
 state BAR_FONT:
284
   font = string
285
       -> call cfg_bar_font($font); BAR

b/src/config_directives.c

290
@@ -495,6 +495,14 @@ CFGFUN(bar_tray_output, const char *output) {
291
     current_bar.tray_output = sstrdup(output);
292
 }
293
 
294
+CFGFUN(bar_tray_icon_size, const long size) {
295
+    current_bar.tray_icon_size = size;
296
+}
297
+
298
+CFGFUN(bar_min_height, const long size) {
299
+    current_bar.min_height = size;
300
+}
301
+
302
 CFGFUN(bar_color_single, const char *colorclass, const char *color) {
303
     if (strcmp(colorclass, "background") == 0)
304
         current_bar.colors.background = sstrdup(color);

b/src/ipc.c

309
@@ -736,6 +736,12 @@ IPC_HANDLER(get_bar_config) {
310
                 break;
311
         }
312
 
313
+        ystr("tray_icon_size");
314
+        y(integer, config->tray_icon_size);
315
+
316
+        ystr("min_height");
317
+        y(integer, config->min_height);
318
+
319
         ystr("position");
320
         if (config->position == P_BOTTOM)
321
             ystr("bottom");