Skip to content

Commit ac691ef

Browse files
committed
DBus PropertiesChanged signal not being emitted for *Length PropertiesChanged
Similarly to what @ammgws noted in dunst-project#765, for `paused`, the various Length PropertiesChanged were not emitting PropertiesChanged when notifications were opened/closed. This change makes sure that these values are always kept up to date.
1 parent e1289f4 commit ac691ef

File tree

4 files changed

+192
-3
lines changed

4 files changed

+192
-3
lines changed

src/dbus.c

+73-3
Original file line numberDiff line numberDiff line change
@@ -694,6 +694,73 @@ static struct notification *dbus_message_to_notification(const gchar *sender, GV
694694
return n;
695695
}
696696

697+
void signal_length_propertieschanged()
698+
{
699+
700+
static unsigned int last_displayed = 0;
701+
static unsigned int last_history = 0;
702+
static unsigned int last_waiting = 0;
703+
704+
if (!dbus_conn)
705+
return;
706+
707+
GVariantBuilder *builder = g_variant_builder_new(G_VARIANT_TYPE_VARDICT);
708+
GVariantBuilder *invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE_STRING_ARRAY);
709+
710+
unsigned int displayed = queues_length_displayed();
711+
unsigned int history = queues_length_history();
712+
unsigned int waiting = queues_length_waiting();
713+
bool properties_changed = false;
714+
715+
if (last_displayed != displayed) {
716+
g_variant_builder_add(builder,
717+
"{sv}",
718+
"displayedLength", g_variant_new_uint32(displayed));
719+
last_displayed = displayed;
720+
properties_changed = true;
721+
}
722+
723+
if (last_history != history) {
724+
g_variant_builder_add(builder,
725+
"{sv}",
726+
"historyLength", g_variant_new_uint32(history));
727+
last_history = history;
728+
properties_changed = true;
729+
}
730+
if (last_waiting != waiting) {
731+
g_variant_builder_add(builder,
732+
"{sv}",
733+
"waitingLength", g_variant_new_uint32(waiting));
734+
last_waiting = waiting;
735+
properties_changed = true;
736+
}
737+
738+
if (properties_changed) {
739+
GVariant *body = g_variant_new("(sa{sv}as)",
740+
DUNST_IFAC,
741+
builder,
742+
invalidated_builder);
743+
744+
GError *err = NULL;
745+
746+
g_dbus_connection_emit_signal(dbus_conn,
747+
NULL,
748+
FDN_PATH,
749+
PROPERTIES_IFAC,
750+
"PropertiesChanged",
751+
body,
752+
&err);
753+
754+
if (err) {
755+
LOG_W("Unable to emit signal: %s", err->message);
756+
g_error_free(err);
757+
}
758+
}
759+
760+
g_clear_pointer(&builder, g_variant_builder_unref);
761+
g_clear_pointer(&invalidated_builder, g_variant_builder_unref);
762+
}
763+
697764
static void dbus_cb_Notify(
698765
GDBusConnection *connection,
699766
const gchar *sender,
@@ -886,21 +953,24 @@ gboolean dbus_cb_dunst_Properties_Set(GDBusConnection *connection,
886953
dunst_status(S_RUNNING, !g_variant_get_boolean(value));
887954
wake_up();
888955

889-
GVariantBuilder *builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
890-
GVariantBuilder *invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
956+
GVariantBuilder *builder = g_variant_builder_new(G_VARIANT_TYPE_VARDICT);
957+
GVariantBuilder *invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE_STRING_ARRAY);
891958
g_variant_builder_add(builder,
892959
"{sv}",
893960
"paused", g_variant_new_boolean(g_variant_get_boolean(value)));
894961
g_dbus_connection_emit_signal(connection,
895962
NULL,
896963
object_path,
897-
"org.freedesktop.DBus.Properties",
964+
PROPERTIES_IFAC,
898965
"PropertiesChanged",
899966
g_variant_new("(sa{sv}as)",
900967
interface_name,
901968
builder,
902969
invalidated_builder),
903970
NULL);
971+
972+
g_clear_pointer(&builder, g_variant_builder_unref);
973+
g_clear_pointer(&invalidated_builder, g_variant_builder_unref);
904974
return true;
905975
}
906976

src/dbus.h

+1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ int dbus_init(void);
2020
void dbus_teardown(int id);
2121
void signal_notification_closed(struct notification *n, enum reason reason);
2222
void signal_action_invoked(const struct notification *n, const char *identifier);
23+
void signal_length_propertieschanged();
2324

2425
#endif
2526
/* vim: set ft=c tabstop=8 shiftwidth=8 expandtab textwidth=0: */

src/queues.c

+1
Original file line numberDiff line numberDiff line change
@@ -547,6 +547,7 @@ void queues_update(struct dunst_status status, gint64 time)
547547
}
548548
}
549549
}
550+
signal_length_propertieschanged();
550551
}
551552

552553
/* see queues.h */

test/dbus.c

+117
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,14 @@ struct signal_actioninvoked {
2121
GDBusConnection *conn;
2222
};
2323

24+
struct signal_propertieschanged {
25+
gchar *interface;
26+
GVariant *array_dict_sv_data;
27+
GVariant *array_s_data;
28+
guint subscription_id;
29+
GDBusConnection *conn;
30+
};
31+
2432
struct signal_closed {
2533
guint32 id;
2634
guint32 reason;
@@ -81,6 +89,73 @@ void dbus_signal_unsubscribe_actioninvoked(struct signal_actioninvoked *actionin
8189
actioninvoked->subscription_id = -1;
8290
}
8391

92+
void dbus_signal_cb_propertieschanged(GDBusConnection *connection,
93+
const gchar *sender_name,
94+
const gchar *object_path,
95+
const gchar *interface_name,
96+
const gchar *signal_name,
97+
GVariant *parameters,
98+
gpointer user_data)
99+
{
100+
g_return_if_fail(user_data);
101+
102+
gchar *interface;
103+
GVariant *array_dict_sv_data;
104+
GVariant *array_s_data;
105+
106+
struct signal_propertieschanged *sig = (struct signal_propertieschanged*) user_data;
107+
108+
g_variant_get(parameters, "(s@a{sv}@as)", &interface, &array_dict_sv_data, &array_s_data);
109+
110+
if (g_strcmp0(interface, DUNST_IFAC) == 0) {
111+
sig->interface = interface;
112+
sig->array_dict_sv_data = array_dict_sv_data;
113+
sig->array_s_data = array_s_data;
114+
}
115+
116+
}
117+
118+
void dbus_signal_subscribe_propertieschanged(struct signal_propertieschanged *propertieschanged)
119+
{
120+
assert(propertieschanged);
121+
122+
propertieschanged->conn = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL);
123+
propertieschanged->subscription_id =
124+
g_dbus_connection_signal_subscribe(
125+
// GDBusConnection *connection,
126+
propertieschanged->conn,
127+
// const gchar *sender,
128+
FDN_NAME,
129+
// const gchar *interface_name,
130+
PROPERTIES_IFAC,
131+
// const gchar *member,
132+
"PropertiesChanged",
133+
// const gchar *object_path,
134+
FDN_PATH,
135+
// const gchar *arg0,
136+
NULL,
137+
// GDBusSignalFlags flags,
138+
G_DBUS_SIGNAL_FLAGS_NONE,
139+
// GDBusSignalCallback callback,
140+
dbus_signal_cb_propertieschanged,
141+
// gpointer user_data,
142+
propertieschanged,
143+
// GDestroyNotify user_data_free_func
144+
NULL);
145+
146+
}
147+
148+
void dbus_signal_unsubscribe_propertieschanged(struct signal_propertieschanged *propertieschanged)
149+
{
150+
assert(propertieschanged);
151+
152+
g_dbus_connection_signal_unsubscribe(propertieschanged->conn, propertieschanged->subscription_id);
153+
g_object_unref(propertieschanged->conn);
154+
155+
propertieschanged->conn = NULL;
156+
propertieschanged->subscription_id = -1;
157+
}
158+
84159
void dbus_signal_cb_closed(GDBusConnection *connection,
85160
const gchar *sender_name,
86161
const gchar *object_path,
@@ -740,6 +815,47 @@ TEST test_signal_actioninvoked(void)
740815
PASS();
741816
}
742817

818+
TEST test_signal_length_propertieschanged(void)
819+
{
820+
struct dbus_notification *n_dbus;
821+
struct signal_propertieschanged sig = {NULL, NULL, NULL, -1};
822+
823+
dbus_signal_subscribe_propertieschanged(&sig);
824+
825+
n_dbus = dbus_notification_new();
826+
n_dbus->app_name = "dunstteststack";
827+
n_dbus->app_icon = "NONE2";
828+
n_dbus->summary = "Headline for New";
829+
n_dbus->body = "Text";
830+
g_hash_table_insert(n_dbus->actions, g_strdup("actionkey"), g_strdup("Print this text"));
831+
832+
guint id;
833+
ASSERT(dbus_notification_fire(n_dbus, &id));
834+
ASSERT(id != 0);
835+
836+
queues_update(STATUS_NORMAL, time_monotonic_now());
837+
838+
uint waiting = 0;
839+
while (!sig.interface && waiting < 2000) {
840+
usleep(500);
841+
waiting++;
842+
}
843+
844+
ASSERT_STR_EQ(sig.interface, DUNST_IFAC);
845+
846+
guint32 displayed_length;
847+
g_variant_lookup(sig.array_dict_sv_data, "displayedLength", "u", &displayed_length);
848+
849+
ASSERT_EQ(displayed_length, queues_length_displayed());
850+
851+
g_free(sig.interface);
852+
g_variant_unref(sig.array_dict_sv_data);
853+
g_variant_unref(sig.array_s_data);
854+
dbus_notification_free(n_dbus);
855+
dbus_signal_unsubscribe_propertieschanged(&sig);
856+
PASS();
857+
}
858+
743859
TEST test_close_and_signal(void)
744860
{
745861
GVariant *data, *ret;
@@ -928,6 +1044,7 @@ gpointer run_threaded_tests(gpointer data)
9281044
RUN_TESTp(test_server_caps, MARKUP_NO);
9291045
RUN_TEST(test_close_and_signal);
9301046
RUN_TEST(test_signal_actioninvoked);
1047+
RUN_TEST(test_signal_length_propertieschanged);
9311048
RUN_TEST(test_timeout_overflow);
9321049
RUN_TEST(test_override_dbus_timeout);
9331050
RUN_TEST(test_match_dbus_timeout);

0 commit comments

Comments
 (0)