18
18
19
19
// TODO implement menu, and use IconThemePath
20
20
21
- static void sni_get_pixmap (struct swaybar_sni * sni , char * prop , list_t * * dest ) {
22
- sd_bus_error error = SD_BUS_ERROR_NULL ;
23
- sd_bus_message * msg ;
24
- int ret = sd_bus_get_property ( sni -> tray -> bus , sni -> service , sni -> path ,
25
- sni -> interface , prop , & error , & msg , "a(iiay)" );
26
- if ( ret < 0 ) {
27
- wlr_log ( WLR_DEBUG , "Failed to get property %s: %s" , prop , error . message );
28
- sd_bus_error_free ( & error );
29
- return ;
30
- }
21
+ static bool sni_ready (struct swaybar_sni * sni ) {
22
+ return sni -> status && ( sni -> status [ 0 ] == 'N' ?
23
+ sni -> attention_icon_name || sni -> attention_icon_pixmap :
24
+ sni -> icon_name || sni -> icon_pixmap );
25
+ }
26
+
27
+ static void set_sni_dirty ( struct swaybar_sni * sni ) {
28
+ sni -> min_size = sni -> max_size = 0 ; // invalidate previous icon
29
+ set_bar_dirty ( sni -> tray -> bar ) ;
30
+ }
31
31
32
- ret = sd_bus_message_enter_container (msg , 'a' , "(iiay)" );
32
+ static int read_pixmap (sd_bus_message * msg , struct swaybar_sni * sni ,
33
+ const char * prop , list_t * * dest ) {
34
+ int ret = sd_bus_message_enter_container (msg , 'a' , "(iiay)" );
33
35
if (ret < 0 ) {
34
36
wlr_log (WLR_DEBUG , "Failed to read property %s: %s" , prop , strerror (- ret ));
35
- return ;
37
+ return ret ;
36
38
}
37
39
38
40
list_t * pixmaps = create_list ();
39
41
if (!pixmaps ) {
40
- return ;
42
+ return -12 ; // -ENOMEM
41
43
}
42
44
43
45
while (!sd_bus_message_at_end (msg , 0 )) {
@@ -46,6 +48,7 @@ static void sni_get_pixmap(struct swaybar_sni *sni, char *prop, list_t **dest) {
46
48
wlr_log (WLR_DEBUG , "Failed to read property %s: %s" , prop , strerror (- ret ));
47
49
goto cleanup ;
48
50
}
51
+
49
52
int size ;
50
53
ret = sd_bus_message_read (msg , "ii" , NULL , & size );
51
54
if (ret < 0 ) {
@@ -71,67 +74,108 @@ static void sni_get_pixmap(struct swaybar_sni *sni, char *prop, list_t **dest) {
71
74
}
72
75
* dest = pixmaps ;
73
76
74
- sd_bus_message_unref (msg );
75
- return ;
77
+ return ret ;
76
78
cleanup :
77
- sd_bus_message_unref (msg );
78
79
list_free_items_and_destroy (pixmaps );
80
+ return ret ;
79
81
}
80
82
81
- static void sni_get_property (struct swaybar_sni * sni , char * prop , char * type ,
82
- void * dest ) {
83
- sd_bus_error error = SD_BUS_ERROR_NULL ;
84
- sd_bus_message * msg ;
85
- int ret = sd_bus_get_property (sni -> tray -> bus , sni -> service , sni -> path ,
86
- sni -> interface , prop , & error , & msg , type );
83
+ struct get_property_data {
84
+ struct swaybar_sni * sni ;
85
+ const char * prop ;
86
+ const char * type ;
87
+ void * dest ;
88
+ };
89
+
90
+ static int get_property_callback (sd_bus_message * msg , void * data ,
91
+ sd_bus_error * error ) {
92
+ struct get_property_data * d = data ;
93
+ struct swaybar_sni * sni = d -> sni ;
94
+ const char * prop = d -> prop ;
95
+ const char * type = d -> type ;
96
+ void * dest = d -> dest ;
97
+
98
+ int ret = 0 ;
99
+ if (sd_bus_message_is_method_error (msg , NULL )) {
100
+ sd_bus_error err = * sd_bus_message_get_error (msg );
101
+ wlr_log (WLR_DEBUG , "Failed to get property %s: %s" , prop , err .message );
102
+ goto cleanup ;
103
+ }
104
+
105
+ ret = sd_bus_message_enter_container (msg , 'v' , type );
87
106
if (ret < 0 ) {
88
- wlr_log (WLR_DEBUG , "Failed to get property %s: %s" , prop , error .message );
89
- sd_bus_error_free (& error );
107
+ wlr_log (WLR_DEBUG , "Failed to read property %s: %s" , prop , strerror (- ret ));
108
+ goto cleanup ;
109
+ }
110
+
111
+ if (!type ) {
112
+ ret = read_pixmap (msg , sni , prop , dest );
113
+ if (ret < 0 ) {
114
+ goto cleanup ;
115
+ }
90
116
} else {
91
117
ret = sd_bus_message_read (msg , type , dest );
92
118
if (ret < 0 ) {
93
- wlr_log (WLR_DEBUG , "Failed to read property %s: %s" , prop , strerror (- ret ));
119
+ wlr_log (WLR_DEBUG , "Failed to read property %s: %s" , prop ,
120
+ strerror (- ret ));
121
+ goto cleanup ;
94
122
} else if (* type == 's' || * type == 'o' ) {
95
123
char * * str = dest ;
96
124
* str = strdup (* str );
97
125
}
98
- sd_bus_message_unref (msg );
99
126
}
127
+
128
+ if (sni_ready (sni )) {
129
+ set_sni_dirty (sni );
130
+ }
131
+
132
+ cleanup :
133
+ free (data );
134
+ return ret ;
100
135
}
101
136
102
- static void set_sni_dirty (struct swaybar_sni * sni ) {
103
- sni -> min_size = sni -> max_size = 0 ; // invalidate previous icon
104
- set_bar_dirty (sni -> tray -> bar );
137
+ static void sni_get_property_async (struct swaybar_sni * sni , const char * prop ,
138
+ const char * type , void * dest ) {
139
+ struct get_property_data * data = malloc (sizeof (struct get_property_data ));
140
+ data -> sni = sni ;
141
+ data -> prop = prop ;
142
+ data -> type = type ;
143
+ data -> dest = dest ;
144
+ int ret = sd_bus_call_method_async (sni -> tray -> bus , NULL , sni -> service ,
145
+ sni -> path , "org.freedesktop.DBus.Properties" , "Get" ,
146
+ get_property_callback , data , "ss" , sni -> interface , prop );
147
+ if (ret < 0 ) {
148
+ wlr_log (WLR_DEBUG , "Failed to get property %s: %s" , prop , strerror (- ret ));
149
+ }
105
150
}
106
151
107
152
static int handle_new_icon (sd_bus_message * msg , void * data , sd_bus_error * error ) {
108
153
struct swaybar_sni * sni = data ;
154
+ wlr_log (WLR_DEBUG , "%s has new IconName" , sni -> watcher_id );
155
+
109
156
free (sni -> icon_name );
110
- sni_get_property (sni , "IconName" , "s" , & sni -> icon_name );
111
- list_free_items_and_destroy (sni -> icon_pixmap );
112
- sni_get_pixmap (sni , "IconPixmap" , & sni -> icon_pixmap );
113
- wlr_log (WLR_DEBUG , "%s has new IconName='%s'" , sni -> watcher_id , sni -> icon_name );
157
+ sni -> icon_name = NULL ;
158
+ sni_get_property_async (sni , "IconName" , "s" , & sni -> icon_name );
114
159
115
- if (sni -> status [ 0 ] != 'N' ) {
116
- set_sni_dirty ( sni ) ;
117
- }
160
+ list_free_items_and_destroy (sni -> icon_pixmap );
161
+ sni -> icon_pixmap = NULL ;
162
+ sni_get_property_async ( sni , "IconPixmap" , NULL , & sni -> icon_pixmap );
118
163
119
164
return 0 ;
120
165
}
121
166
122
167
static int handle_new_attention_icon (sd_bus_message * msg , void * data ,
123
168
sd_bus_error * error ) {
124
169
struct swaybar_sni * sni = data ;
170
+ wlr_log (WLR_DEBUG , "%s has new AttentionIconName" , sni -> watcher_id );
171
+
125
172
free (sni -> attention_icon_name );
126
- sni_get_property (sni , "AttentionIconName" , "s" , & sni -> attention_icon_name );
127
- list_free_items_and_destroy (sni -> attention_icon_pixmap );
128
- sni_get_pixmap (sni , "IconPixmap" , & sni -> attention_icon_pixmap );
129
- wlr_log (WLR_DEBUG , "%s has new AttentionIconName='%s'" , sni -> watcher_id ,
130
- sni -> attention_icon_name );
173
+ sni -> attention_icon_name = NULL ;
174
+ sni_get_property_async (sni , "AttentionIconName" , "s" , & sni -> attention_icon_name );
131
175
132
- if (sni -> status [ 0 ] == 'N' ) {
133
- set_sni_dirty ( sni ) ;
134
- }
176
+ list_free_items_and_destroy (sni -> attention_icon_pixmap );
177
+ sni -> attention_icon_pixmap = NULL ;
178
+ sni_get_property_async ( sni , "AttentionIconPixmap" , NULL , & sni -> attention_icon_pixmap );
135
179
136
180
return 0 ;
137
181
}
@@ -145,7 +189,7 @@ static int handle_new_status(sd_bus_message *msg, void *data, sd_bus_error *erro
145
189
struct swaybar_sni * sni = data ;
146
190
free (sni -> status );
147
191
sni -> status = strdup (status );
148
- wlr_log (WLR_DEBUG , "%s has new Status= '%s'" , sni -> watcher_id , status );
192
+ wlr_log (WLR_DEBUG , "%s has new Status '%s'" , sni -> watcher_id , status );
149
193
set_sni_dirty (sni );
150
194
}
151
195
return ret ;
@@ -181,18 +225,13 @@ struct swaybar_sni *create_sni(char *id, struct swaybar_tray *tray) {
181
225
182
226
// Ignored: Category, Id, Title, WindowId, OverlayIconName,
183
227
// OverlayIconPixmap, AttentionMovieName, ToolTip
184
- sni_get_property (sni , "Status" , "s" , & sni -> status );
185
- sni_get_property (sni , "IconName" , "s" , & sni -> icon_name );
186
- sni_get_pixmap (sni , "IconPixmap" , & sni -> icon_pixmap );
187
- sni_get_property (sni , "AttentionIconName" , "s" , & sni -> attention_icon_name );
188
- sni_get_pixmap (sni , "AttentionIconPixmap" , & sni -> attention_icon_pixmap );
189
- sni_get_property (sni , "ItemIsMenu" , "b" , & sni -> item_is_menu );
190
- sni_get_property (sni , "Menu" , "o" , & sni -> menu );
191
-
192
- wlr_log (WLR_DEBUG , "Properties: Status='%s' IconName='%s' "
193
- "AttentionIconName='%s' ItemIsMenu=%s Menu='%s'" ,
194
- sni -> status , sni -> icon_name , sni -> attention_icon_name ,
195
- sni -> item_is_menu ? "true" : "false" , sni -> menu );
228
+ sni_get_property_async (sni , "Status" , "s" , & sni -> status );
229
+ sni_get_property_async (sni , "IconName" , "s" , & sni -> icon_name );
230
+ sni_get_property_async (sni , "IconPixmap" , NULL , & sni -> icon_pixmap );
231
+ sni_get_property_async (sni , "AttentionIconName" , "s" , & sni -> attention_icon_name );
232
+ sni_get_property_async (sni , "AttentionIconPixmap" , NULL , & sni -> attention_icon_pixmap );
233
+ sni_get_property_async (sni , "ItemIsMenu" , "b" , & sni -> item_is_menu );
234
+ sni_get_property_async (sni , "Menu" , "o" , & sni -> menu );
196
235
197
236
sni_match_signal (sni , "NewIcon" , handle_new_icon );
198
237
sni_match_signal (sni , "NewAttentionIcon" , handle_new_attention_icon );
@@ -292,43 +331,12 @@ static enum hotspot_event_handling icon_hotspot_callback(
292
331
return HOTSPOT_PROCESS ;
293
332
}
294
333
295
- static bool sni_ready (struct swaybar_sni * sni ) { // TODO remove
296
- if (!sni -> status ) {
297
- sni_get_property (sni , "Status" , "s" , & sni -> status );
298
- if (!sni -> status ) {
299
- return false;
300
- }
301
- }
302
-
303
- if (sni -> status [0 ] == 'N' ) { // NeedsAttention
304
- if (!sni -> attention_icon_name ) {
305
- sni_get_property (sni , "AttentionIconName" , "s" , & sni -> attention_icon_name );
306
- }
307
- if (!sni -> attention_icon_name && !sni -> attention_icon_pixmap ) {
308
- sni_get_pixmap (sni , "AttentionIconPixmap" , & sni -> attention_icon_pixmap );
309
- }
310
- return sni -> attention_icon_name || sni -> attention_icon_pixmap ;
311
- } else {
312
- if (!sni -> icon_name ) {
313
- sni_get_property (sni , "IconName" , "s" , & sni -> icon_name );
314
- }
315
- if (!sni -> icon_name && !sni -> icon_pixmap ) {
316
- sni_get_pixmap (sni , "IconPixmap" , & sni -> icon_pixmap );
317
- }
318
- return sni -> icon_name || sni -> icon_pixmap ;
319
- }
320
- }
321
-
322
334
uint32_t render_sni (cairo_t * cairo , struct swaybar_output * output , double * x ,
323
335
struct swaybar_sni * sni ) {
324
- if (!sni_ready (sni )) {
325
- return 0 ;
326
- }
327
336
uint32_t height = output -> height * output -> scale ;
328
337
int padding = output -> bar -> config -> tray_padding ;
329
338
int ideal_size = height - 2 * padding ;
330
-
331
- if (ideal_size < sni -> min_size || ideal_size > sni -> max_size ) {
339
+ if ((ideal_size < sni -> min_size || ideal_size > sni -> max_size ) && sni_ready (sni )) {
332
340
bool icon_found = false;
333
341
char * icon_name = sni -> status [0 ] == 'N' ?
334
342
sni -> attention_icon_name : sni -> icon_name ;
@@ -367,6 +375,7 @@ uint32_t render_sni(cairo_t *cairo, struct swaybar_output *output, double *x,
367
375
}
368
376
}
369
377
if (!sni -> icon ) {
378
+ // TODO fallback
370
379
return 0 ;
371
380
}
372
381
0 commit comments