Merge pull request #651 from bebehei/dunstctl
Implement a command line control (dunstctl)
This commit is contained in:
commit
337ff1edb5
25
Makefile
25
Makefile
@ -106,9 +106,15 @@ test/test: ${OBJ} ${TEST_OBJ}
|
|||||||
${CC} -o ${@} ${TEST_OBJ} $(filter-out ${TEST_OBJ:test/%=src/%},${OBJ}) ${CFLAGS} ${LDFLAGS}
|
${CC} -o ${@} ${TEST_OBJ} $(filter-out ${TEST_OBJ:test/%=src/%},${OBJ}) ${CFLAGS} ${LDFLAGS}
|
||||||
|
|
||||||
.PHONY: doc doc-doxygen
|
.PHONY: doc doc-doxygen
|
||||||
doc: docs/dunst.1
|
doc: docs/dunst.1 docs/dunstctl.1
|
||||||
|
|
||||||
|
# Can't dedup this as we need to explicitly provide the name and title text to
|
||||||
|
# pod2man :(
|
||||||
docs/dunst.1: docs/dunst.pod
|
docs/dunst.1: docs/dunst.pod
|
||||||
${POD2MAN} --name=dunst -c "Dunst Reference" --section=1 --release=${VERSION} $< > $@
|
${POD2MAN} --name=dunst -c "Dunst Reference" --section=1 --release=${VERSION} $< > $@
|
||||||
|
docs/dunstctl.1: docs/dunstctl.pod
|
||||||
|
${POD2MAN} --name=dunstctl -c "dunstctl reference" --section=1 --release=${VERSION} $< > $@
|
||||||
|
|
||||||
doc-doxygen:
|
doc-doxygen:
|
||||||
${DOXYGEN} docs/internal/Doxyfile
|
${DOXYGEN} docs/internal/Doxyfile
|
||||||
|
|
||||||
@ -137,6 +143,7 @@ clean-dunstify:
|
|||||||
|
|
||||||
clean-doc:
|
clean-doc:
|
||||||
rm -f docs/dunst.1
|
rm -f docs/dunst.1
|
||||||
|
rm -f docs/dunstctl.1
|
||||||
rm -fr docs/internal/html
|
rm -fr docs/internal/html
|
||||||
rm -fr docs/internal/coverage
|
rm -fr docs/internal/coverage
|
||||||
|
|
||||||
@ -151,15 +158,19 @@ clean-coverage-run:
|
|||||||
${FIND} . -type f -name '*.gcov' -delete
|
${FIND} . -type f -name '*.gcov' -delete
|
||||||
${FIND} . -type f -name '*.gcda' -delete
|
${FIND} . -type f -name '*.gcda' -delete
|
||||||
|
|
||||||
.PHONY: install install-dunst install-doc \
|
.PHONY: install install-dunst install-dunstctl install-doc \
|
||||||
install-service install-service-dbus install-service-systemd \
|
install-service install-service-dbus install-service-systemd \
|
||||||
uninstall \
|
uninstall uninstall-dunstctl \
|
||||||
uninstall-service uninstall-service-dbus uninstall-service-systemd
|
uninstall-service uninstall-service-dbus uninstall-service-systemd
|
||||||
install: install-dunst install-doc install-service install-dunstify
|
install: install-dunst install-dunstctl install-doc install-service install-dunstify
|
||||||
|
|
||||||
install-dunst: dunst doc
|
install-dunst: dunst doc
|
||||||
install -Dm755 dunst ${DESTDIR}${BINDIR}/dunst
|
install -Dm755 dunst ${DESTDIR}${BINDIR}/dunst
|
||||||
install -Dm644 docs/dunst.1 ${DESTDIR}${MANPREFIX}/man1/dunst.1
|
install -Dm644 docs/dunst.1 ${DESTDIR}${MANPREFIX}/man1/dunst.1
|
||||||
|
install -Dm644 docs/dunstctl.1 ${DESTDIR}${MANPREFIX}/man1/dunstctl.1
|
||||||
|
|
||||||
|
install-dunstctl: dunstctl
|
||||||
|
install -Dm755 dunstctl ${DESTDIR}${BINDIR}/dunstctl
|
||||||
|
|
||||||
install-doc:
|
install-doc:
|
||||||
install -Dm644 dunstrc ${DESTDIR}${DATADIR}/dunst/dunstrc
|
install -Dm644 dunstrc ${DESTDIR}${DATADIR}/dunst/dunstrc
|
||||||
@ -176,12 +187,16 @@ endif
|
|||||||
install-dunstify: dunstify
|
install-dunstify: dunstify
|
||||||
install -Dm755 dunstify ${DESTDIR}${BINDIR}/dunstify
|
install -Dm755 dunstify ${DESTDIR}${BINDIR}/dunstify
|
||||||
|
|
||||||
uninstall: uninstall-service
|
uninstall: uninstall-service uninstall-dunstctl
|
||||||
rm -f ${DESTDIR}${BINDIR}/dunst
|
rm -f ${DESTDIR}${BINDIR}/dunst
|
||||||
rm -f ${DESTDIR}${BINDIR}/dunstify
|
rm -f ${DESTDIR}${BINDIR}/dunstify
|
||||||
rm -f ${DESTDIR}${MANPREFIX}/man1/dunst.1
|
rm -f ${DESTDIR}${MANPREFIX}/man1/dunst.1
|
||||||
|
rm -f ${DESTDIR}${MANPREFIX}/man1/dunstctl.1
|
||||||
rm -rf ${DESTDIR}${DATADIR}/dunst
|
rm -rf ${DESTDIR}${DATADIR}/dunst
|
||||||
|
|
||||||
|
uninstall-dunstctl:
|
||||||
|
rm -f ${DESTDIR}${BINDIR}/dunstctl
|
||||||
|
|
||||||
uninstall-service: uninstall-service-dbus
|
uninstall-service: uninstall-service-dbus
|
||||||
uninstall-service-dbus:
|
uninstall-service-dbus:
|
||||||
rm -f ${DESTDIR}${SERVICEDIR_DBUS}/org.knopwob.dunst.service
|
rm -f ${DESTDIR}${SERVICEDIR_DBUS}/org.knopwob.dunst.service
|
||||||
|
@ -517,7 +517,7 @@ Close all notifications.
|
|||||||
|
|
||||||
=back
|
=back
|
||||||
|
|
||||||
=head2 Shortcut section
|
=head2 Shortcut section B<DEPRECATED SEE DUNSTCTL>
|
||||||
|
|
||||||
Keyboard shortcuts are defined in the following format: "Modifier+key" where the
|
Keyboard shortcuts are defined in the following format: "Modifier+key" where the
|
||||||
modifier is one of ctrl,mod1,mod2,mod3,mod4 and key is any keyboard key.
|
modifier is one of ctrl,mod1,mod2,mod3,mod4 and key is any keyboard key.
|
||||||
@ -602,6 +602,13 @@ See TIME FORMAT for valid times.
|
|||||||
|
|
||||||
=back
|
=back
|
||||||
|
|
||||||
|
=head1 DUNSTCTL
|
||||||
|
|
||||||
|
Dunst now contains a command line control command that can be used to interact
|
||||||
|
with it. It supports all functions previously done only via keyboard shortcuts
|
||||||
|
but also has a lot of extra functionality. So see more see the dunstctl man
|
||||||
|
page.
|
||||||
|
|
||||||
=head1 HISTORY
|
=head1 HISTORY
|
||||||
|
|
||||||
Dunst saves a number of notifications (specified by B<history_length>) in memory.
|
Dunst saves a number of notifications (specified by B<history_length>) in memory.
|
||||||
@ -865,9 +872,8 @@ Example time: "1000ms" "10m"
|
|||||||
|
|
||||||
=head1 MISCELLANEOUS
|
=head1 MISCELLANEOUS
|
||||||
|
|
||||||
Dunst can be paused by sending a notification with a summary of
|
Dunst can be paused via the `dunstctl set-running false` command. To unpause dunst use
|
||||||
"DUNST_COMMAND_PAUSE", resumed with a summary of "DUNST_COMMAND_RESUME" and
|
`dunstctl set-status true` and to unpause `dunstctl set-status false`.
|
||||||
toggled with a summary of "DUNST_COMMAND_TOGGLE".
|
|
||||||
Alternatively you can send SIGUSR1 and SIGUSR2 to pause and unpause
|
Alternatively you can send SIGUSR1 and SIGUSR2 to pause and unpause
|
||||||
respectively. For Example:
|
respectively. For Example:
|
||||||
|
|
||||||
@ -908,4 +914,4 @@ If you feel that copyrights are violated, please send me an email.
|
|||||||
|
|
||||||
=head1 SEE ALSO
|
=head1 SEE ALSO
|
||||||
|
|
||||||
dwm(1), dmenu(1), twmn(1), notify-send(1)
|
dunstctl(1), dwm(1), dmenu(1), twmn(1), notify-send(1)
|
||||||
|
59
docs/dunstctl.pod
Normal file
59
docs/dunstctl.pod
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
=head1 NAME
|
||||||
|
|
||||||
|
dunstctl - Command line control utility for dunst, a customizable and lightweight notification-daemon
|
||||||
|
|
||||||
|
=head1 SYNOPSIS
|
||||||
|
|
||||||
|
dunstctl COMMAND [PARAMETER]
|
||||||
|
|
||||||
|
=head1 COMMANDS
|
||||||
|
|
||||||
|
=over 4
|
||||||
|
|
||||||
|
=item B<action> notification_position
|
||||||
|
|
||||||
|
Performs the default action or, if not available, opens the context menu of the
|
||||||
|
notification at the given position (starting count at the top, first
|
||||||
|
notification being 0).
|
||||||
|
|
||||||
|
=item B<close>
|
||||||
|
|
||||||
|
Close the topmost notification currently being displayed.
|
||||||
|
|
||||||
|
=item B<close-all>
|
||||||
|
|
||||||
|
Close all notifications currently being displayed
|
||||||
|
|
||||||
|
=item B<context>
|
||||||
|
|
||||||
|
Open the context menu, presenting all available actions and urls for the
|
||||||
|
currently open notifications.
|
||||||
|
|
||||||
|
=item B<history-pop>
|
||||||
|
|
||||||
|
Redisplay the notification that was most recently closed. This can be called
|
||||||
|
multiple times to show older notifications, up to the history limit configured
|
||||||
|
in dunst.
|
||||||
|
|
||||||
|
=item B<running>
|
||||||
|
|
||||||
|
Check if dunst is currently running or paused. If dunst is paused notifications
|
||||||
|
will be kept but not shown until it is unpaused.
|
||||||
|
|
||||||
|
=item B<set-running> true/false
|
||||||
|
|
||||||
|
Set the paused status of dunst. If true, dunst is running normally, if false,
|
||||||
|
dunst is paused. See the running command and the dunst man page for more
|
||||||
|
information.
|
||||||
|
|
||||||
|
=item B<debug>
|
||||||
|
|
||||||
|
Tries to contact dunst and checks for common faults between dunstctl and dunst.
|
||||||
|
Useful if something isn't working
|
||||||
|
|
||||||
|
=item B<help>
|
||||||
|
|
||||||
|
Show all available commands with a brief description
|
||||||
|
|
||||||
|
=back
|
||||||
|
|
101
dunstctl
Executable file
101
dunstctl
Executable file
@ -0,0 +1,101 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
set -eu
|
||||||
|
|
||||||
|
DBUS_NAME="org.freedesktop.Notifications"
|
||||||
|
DBUS_PATH="/org/freedesktop/Notifications"
|
||||||
|
DBUS_IFAC_DUNST="org.dunstproject.cmd0"
|
||||||
|
DBUS_IFAC_PROP="org.freedesktop.DBus.Properties"
|
||||||
|
DBUS_IFAC_FDN="org.freedesktop.Notifications"
|
||||||
|
|
||||||
|
die(){ printf "%s\n" "${1}" >&2; exit 1; }
|
||||||
|
|
||||||
|
show_help() {
|
||||||
|
cat <<-EOH
|
||||||
|
Usage: dunstctl <command> [parameters]"
|
||||||
|
Commands:
|
||||||
|
action Perform the default action, or open the
|
||||||
|
context menu of the notification at the
|
||||||
|
given position
|
||||||
|
close Close the last notification
|
||||||
|
close-all Close the all notifications
|
||||||
|
context Open context menu
|
||||||
|
history-pop Pop one notification from history
|
||||||
|
running Check if dunst is running or paused
|
||||||
|
set-running [true|false] Set the pause status
|
||||||
|
debug Print debugging information
|
||||||
|
help Show this help
|
||||||
|
EOH
|
||||||
|
}
|
||||||
|
dbus_send_checked() {
|
||||||
|
dbus-send "$@" \
|
||||||
|
|| die "Failed to communicate with dunst, is it running? Or maybe the version is outdated. You can try 'dunstctl debug' as a next debugging step."
|
||||||
|
}
|
||||||
|
|
||||||
|
method_call() {
|
||||||
|
dbus_send_checked --print-reply=literal --dest="${DBUS_NAME}" "${DBUS_PATH}" "$@"
|
||||||
|
}
|
||||||
|
|
||||||
|
property_get() {
|
||||||
|
dbus_send_checked --print-reply=literal --dest="${DBUS_NAME}" "${DBUS_PATH}" "${DBUS_IFAC_PROP}.Get" "string:${DBUS_IFAC_DUNST}" "string:${1}"
|
||||||
|
}
|
||||||
|
|
||||||
|
property_set() {
|
||||||
|
dbus_send_checked --print-reply=literal --dest="${DBUS_NAME}" "${DBUS_PATH}" "${DBUS_IFAC_PROP}.Set" "string:${DBUS_IFAC_DUNST}" "string:${1}" "${2}"
|
||||||
|
}
|
||||||
|
|
||||||
|
command -v dbus-send >/dev/null 2>/dev/null || \
|
||||||
|
die "Command dbus-send not found"
|
||||||
|
|
||||||
|
|
||||||
|
case "${1:-}" in
|
||||||
|
"action")
|
||||||
|
method_call "${DBUS_IFAC_DUNST}.NotificationAction" "int32:${2:-0}" >/dev/null
|
||||||
|
;;
|
||||||
|
"close")
|
||||||
|
method_call "${DBUS_IFAC_DUNST}.NotificationCloseLast" >/dev/null
|
||||||
|
;;
|
||||||
|
"close-all")
|
||||||
|
method_call "${DBUS_IFAC_DUNST}.NotificationCloseAll" >/dev/null
|
||||||
|
;;
|
||||||
|
"context")
|
||||||
|
method_call "${DBUS_IFAC_DUNST}.ContextMenuCall" >/dev/null
|
||||||
|
;;
|
||||||
|
"history-pop")
|
||||||
|
method_call "${DBUS_IFAC_DUNST}.NotificationShow" >/dev/null
|
||||||
|
;;
|
||||||
|
"running")
|
||||||
|
property_get running | ( read -r _ _ paused; printf "%s\n" "${paused}"; )
|
||||||
|
;;
|
||||||
|
"set-running")
|
||||||
|
[ "${2:-}" ] \
|
||||||
|
|| die "No status parameter specified. Please give either 'true' or 'false' as running parameter."
|
||||||
|
[ "${2}" = "true" ] || [ "${2}" = "false" ] \
|
||||||
|
|| die "Please give either 'true' or 'false' as running parameter."
|
||||||
|
property_set running variant:boolean:"${2}"
|
||||||
|
;;
|
||||||
|
"help"|"--help"|"-h")
|
||||||
|
show_help
|
||||||
|
;;
|
||||||
|
"debug")
|
||||||
|
dbus-send --print-reply=literal --dest="${DBUS_NAME}" "${DBUS_PATH}" "${DBUS_IFAC_FDN}.GetServerInformation" >/dev/null 2>/dev/null \
|
||||||
|
|| die "Dunst is not running."
|
||||||
|
|
||||||
|
dbus-send --print-reply=literal --dest="${DBUS_NAME}" "${DBUS_PATH}" "${DBUS_IFAC_FDN}.GetServerInformation" \
|
||||||
|
| (
|
||||||
|
read -r name _ version _
|
||||||
|
[ "${name}" = "dunst" ]
|
||||||
|
printf "dunst version: %s\n" "${version}"
|
||||||
|
) \
|
||||||
|
|| die "Another notification manager is running. It's not dunst"
|
||||||
|
|
||||||
|
dbus-send --print-reply=literal --dest="${DBUS_NAME}" "${DBUS_PATH}" "${DBUS_IFAC_DUNST}.Ping" >/dev/null 2>/dev/null \
|
||||||
|
|| die "Dunst controlling interface not available. Is the version too old?"
|
||||||
|
;;
|
||||||
|
"")
|
||||||
|
die "dunstctl: No command specified. Please consult the usage."
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
die "dunstctl: unrecognized command '${1:-}'. Please consult the usage."
|
||||||
|
;;
|
||||||
|
esac
|
269
src/dbus.c
269
src/dbus.c
@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
#include "dunst.h"
|
#include "dunst.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
#include "menu.h"
|
||||||
#include "notification.h"
|
#include "notification.h"
|
||||||
#include "queues.h"
|
#include "queues.h"
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
@ -17,6 +18,12 @@
|
|||||||
#define FDN_IFAC "org.freedesktop.Notifications"
|
#define FDN_IFAC "org.freedesktop.Notifications"
|
||||||
#define FDN_NAME "org.freedesktop.Notifications"
|
#define FDN_NAME "org.freedesktop.Notifications"
|
||||||
|
|
||||||
|
#define DUNST_PATH "/org/freedesktop/Notifications"
|
||||||
|
#define DUNST_IFAC "org.dunstproject.cmd0"
|
||||||
|
#define DUNST_NAME "org.freedesktop.Notifications"
|
||||||
|
|
||||||
|
#define PROPERTIES_IFAC "org.freedesktop.DBus.Properties"
|
||||||
|
|
||||||
GDBusConnection *dbus_conn;
|
GDBusConnection *dbus_conn;
|
||||||
|
|
||||||
static GDBusNodeInfo *introspection_data = NULL;
|
static GDBusNodeInfo *introspection_data = NULL;
|
||||||
@ -62,7 +69,23 @@ static const char *introspection_xml =
|
|||||||
" <arg name=\"id\" type=\"u\"/>"
|
" <arg name=\"id\" type=\"u\"/>"
|
||||||
" <arg name=\"action_key\" type=\"s\"/>"
|
" <arg name=\"action_key\" type=\"s\"/>"
|
||||||
" </signal>"
|
" </signal>"
|
||||||
" </interface>"
|
" </interface>"
|
||||||
|
" <interface name=\""DUNST_IFAC"\">"
|
||||||
|
|
||||||
|
" <method name=\"ContextMenuCall\" />"
|
||||||
|
" <method name=\"NotificationAction\">"
|
||||||
|
" <arg name=\"number\" type=\"i\"/>"
|
||||||
|
" </method>"
|
||||||
|
" <method name=\"NotificationCloseLast\" />"
|
||||||
|
" <method name=\"NotificationCloseAll\" />"
|
||||||
|
" <method name=\"NotificationShow\" />"
|
||||||
|
" <method name=\"Ping\" />"
|
||||||
|
|
||||||
|
" <property name=\"running\" type=\"b\" access=\"readwrite\">"
|
||||||
|
" <annotation name=\"org.freedesktop.DBus.Property.EmitsChangedSignal\" value=\"true\"/>"
|
||||||
|
" </property>"
|
||||||
|
|
||||||
|
" </interface>"
|
||||||
"</node>";
|
"</node>";
|
||||||
|
|
||||||
static const char *stack_tag_hints[] = {
|
static const char *stack_tag_hints[] = {
|
||||||
@ -98,7 +121,6 @@ DBUS_METHOD(Notify);
|
|||||||
DBUS_METHOD(CloseNotification);
|
DBUS_METHOD(CloseNotification);
|
||||||
DBUS_METHOD(GetCapabilities);
|
DBUS_METHOD(GetCapabilities);
|
||||||
DBUS_METHOD(GetServerInformation);
|
DBUS_METHOD(GetServerInformation);
|
||||||
|
|
||||||
static struct dbus_method methods_fdn[] = {
|
static struct dbus_method methods_fdn[] = {
|
||||||
{"CloseNotification", dbus_cb_CloseNotification},
|
{"CloseNotification", dbus_cb_CloseNotification},
|
||||||
{"GetCapabilities", dbus_cb_GetCapabilities},
|
{"GetCapabilities", dbus_cb_GetCapabilities},
|
||||||
@ -106,7 +128,7 @@ static struct dbus_method methods_fdn[] = {
|
|||||||
{"Notify", dbus_cb_Notify},
|
{"Notify", dbus_cb_Notify},
|
||||||
};
|
};
|
||||||
|
|
||||||
void handle_method_call(GDBusConnection *connection,
|
void dbus_cb_fdn_methods(GDBusConnection *connection,
|
||||||
const gchar *sender,
|
const gchar *sender,
|
||||||
const gchar *object_path,
|
const gchar *object_path,
|
||||||
const gchar *interface_name,
|
const gchar *interface_name,
|
||||||
@ -115,12 +137,12 @@ void handle_method_call(GDBusConnection *connection,
|
|||||||
GDBusMethodInvocation *invocation,
|
GDBusMethodInvocation *invocation,
|
||||||
gpointer user_data)
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
struct dbus_method *m = bsearch(
|
|
||||||
method_name,
|
struct dbus_method *m = bsearch(method_name,
|
||||||
&methods_fdn,
|
methods_fdn,
|
||||||
G_N_ELEMENTS(methods_fdn),
|
G_N_ELEMENTS(methods_fdn),
|
||||||
sizeof(struct dbus_method),
|
sizeof(struct dbus_method),
|
||||||
cmp_methods);
|
cmp_methods);
|
||||||
|
|
||||||
if (m) {
|
if (m) {
|
||||||
m->method(connection, sender, parameters, invocation);
|
m->method(connection, sender, parameters, invocation);
|
||||||
@ -131,6 +153,144 @@ void handle_method_call(GDBusConnection *connection,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DBUS_METHOD(dunst_ContextMenuCall);
|
||||||
|
DBUS_METHOD(dunst_NotificationAction);
|
||||||
|
DBUS_METHOD(dunst_NotificationCloseAll);
|
||||||
|
DBUS_METHOD(dunst_NotificationCloseLast);
|
||||||
|
DBUS_METHOD(dunst_NotificationShow);
|
||||||
|
DBUS_METHOD(dunst_Ping);
|
||||||
|
static struct dbus_method methods_dunst[] = {
|
||||||
|
{"ContextMenuCall", dbus_cb_dunst_ContextMenuCall},
|
||||||
|
{"NotificationAction", dbus_cb_dunst_NotificationAction},
|
||||||
|
{"NotificationCloseAll", dbus_cb_dunst_NotificationCloseAll},
|
||||||
|
{"NotificationCloseLast", dbus_cb_dunst_NotificationCloseLast},
|
||||||
|
{"NotificationShow", dbus_cb_dunst_NotificationShow},
|
||||||
|
{"Ping", dbus_cb_dunst_Ping},
|
||||||
|
};
|
||||||
|
|
||||||
|
void dbus_cb_dunst_methods(GDBusConnection *connection,
|
||||||
|
const gchar *sender,
|
||||||
|
const gchar *object_path,
|
||||||
|
const gchar *interface_name,
|
||||||
|
const gchar *method_name,
|
||||||
|
GVariant *parameters,
|
||||||
|
GDBusMethodInvocation *invocation,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
|
||||||
|
struct dbus_method *m = bsearch(method_name,
|
||||||
|
methods_dunst,
|
||||||
|
G_N_ELEMENTS(methods_dunst),
|
||||||
|
sizeof(struct dbus_method),
|
||||||
|
cmp_methods);
|
||||||
|
|
||||||
|
if (m) {
|
||||||
|
m->method(connection, sender, parameters, invocation);
|
||||||
|
} else {
|
||||||
|
LOG_M("Unknown method name: '%s' (sender: '%s').",
|
||||||
|
method_name,
|
||||||
|
sender);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dbus_cb_dunst_ContextMenuCall(GDBusConnection *connection,
|
||||||
|
const gchar *sender,
|
||||||
|
GVariant *parameters,
|
||||||
|
GDBusMethodInvocation *invocation)
|
||||||
|
{
|
||||||
|
LOG_D("CMD: Calling context menu");
|
||||||
|
context_menu();
|
||||||
|
|
||||||
|
g_dbus_method_invocation_return_value(invocation, NULL);
|
||||||
|
g_dbus_connection_flush(connection, NULL, NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dbus_cb_dunst_NotificationAction(GDBusConnection *connection,
|
||||||
|
const gchar *sender,
|
||||||
|
GVariant *parameters,
|
||||||
|
GDBusMethodInvocation *invocation)
|
||||||
|
{
|
||||||
|
int notification_nr = 0;
|
||||||
|
g_variant_get(parameters, "(i)", ¬ification_nr);
|
||||||
|
|
||||||
|
LOG_D("CMD: Calling action for notification %d", notification_nr);
|
||||||
|
|
||||||
|
if (notification_nr < 0 || queues_length_waiting() < notification_nr) {
|
||||||
|
g_dbus_method_invocation_return_error(invocation,
|
||||||
|
G_DBUS_ERROR,
|
||||||
|
G_DBUS_ERROR_INVALID_ARGS,
|
||||||
|
"Couldn't activate action for notification in position %d, %d notifications currently open",
|
||||||
|
notification_nr, queues_length_waiting());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const GList *list = g_list_nth_data(queues_get_displayed(), notification_nr);
|
||||||
|
|
||||||
|
if (list && list->data) {
|
||||||
|
struct notification *n = list->data;
|
||||||
|
LOG_D("CMD: Calling action for notification %s", n->summary);
|
||||||
|
notification_do_action(n);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_dbus_method_invocation_return_value(invocation, NULL);
|
||||||
|
g_dbus_connection_flush(connection, NULL, NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dbus_cb_dunst_NotificationCloseAll(GDBusConnection *connection,
|
||||||
|
const gchar *sender,
|
||||||
|
GVariant *parameters,
|
||||||
|
GDBusMethodInvocation *invocation)
|
||||||
|
{
|
||||||
|
LOG_D("CMD: Pushing all to history");
|
||||||
|
queues_history_push_all();
|
||||||
|
wake_up();
|
||||||
|
|
||||||
|
g_dbus_method_invocation_return_value(invocation, NULL);
|
||||||
|
g_dbus_connection_flush(connection, NULL, NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dbus_cb_dunst_NotificationCloseLast(GDBusConnection *connection,
|
||||||
|
const gchar *sender,
|
||||||
|
GVariant *parameters,
|
||||||
|
GDBusMethodInvocation *invocation)
|
||||||
|
{
|
||||||
|
LOG_D("CMD: Closing last notification");
|
||||||
|
const GList *list = queues_get_displayed();
|
||||||
|
if (list && list->data) {
|
||||||
|
struct notification *n = list->data;
|
||||||
|
queues_notification_close_id(n->id, REASON_USER);
|
||||||
|
wake_up();
|
||||||
|
}
|
||||||
|
|
||||||
|
g_dbus_method_invocation_return_value(invocation, NULL);
|
||||||
|
g_dbus_connection_flush(connection, NULL, NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dbus_cb_dunst_NotificationShow(GDBusConnection *connection,
|
||||||
|
const gchar *sender,
|
||||||
|
GVariant *parameters,
|
||||||
|
GDBusMethodInvocation *invocation)
|
||||||
|
{
|
||||||
|
LOG_D("CMD: Showing last notification from history");
|
||||||
|
queues_history_pop();
|
||||||
|
wake_up();
|
||||||
|
|
||||||
|
g_dbus_method_invocation_return_value(invocation, NULL);
|
||||||
|
g_dbus_connection_flush(connection, NULL, NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Just a simple Ping command to give the ability to dunstctl to test for the existence of this interface
|
||||||
|
* Any other way requires parsing the XML of the Introspection or other foo. Just calling the Ping on an old dunst version will fail. */
|
||||||
|
static void dbus_cb_dunst_Ping(GDBusConnection *connection,
|
||||||
|
const gchar *sender,
|
||||||
|
GVariant *parameters,
|
||||||
|
GDBusMethodInvocation *invocation)
|
||||||
|
{
|
||||||
|
g_dbus_method_invocation_return_value(invocation, NULL);
|
||||||
|
g_dbus_connection_flush(connection, NULL, NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void dbus_cb_GetCapabilities(
|
static void dbus_cb_GetCapabilities(
|
||||||
GDBusConnection *connection,
|
GDBusConnection *connection,
|
||||||
const gchar *sender,
|
const gchar *sender,
|
||||||
@ -347,11 +507,9 @@ static void dbus_cb_GetServerInformation(
|
|||||||
GVariant *parameters,
|
GVariant *parameters,
|
||||||
GDBusMethodInvocation *invocation)
|
GDBusMethodInvocation *invocation)
|
||||||
{
|
{
|
||||||
GVariant *value;
|
GVariant *answer = g_variant_new("(ssss)", "dunst", "knopwob", VERSION, "1.2");
|
||||||
|
|
||||||
value = g_variant_new("(ssss)", "dunst", "knopwob", VERSION, "1.2");
|
|
||||||
g_dbus_method_invocation_return_value(invocation, value);
|
|
||||||
|
|
||||||
|
g_dbus_method_invocation_return_value(invocation, answer);
|
||||||
g_dbus_connection_flush(connection, NULL, NULL, NULL);
|
g_dbus_connection_flush(connection, NULL, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -420,28 +578,81 @@ void signal_action_invoked(const struct notification *n, const char *identifier)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static const GDBusInterfaceVTable interface_vtable = {
|
GVariant *dbus_cb_dunst_Properties_Get(GDBusConnection *connection,
|
||||||
handle_method_call
|
const gchar *sender,
|
||||||
|
const gchar *object_path,
|
||||||
|
const gchar *interface_name,
|
||||||
|
const gchar *property_name,
|
||||||
|
GError **error,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
struct dunst_status status = dunst_status_get();
|
||||||
|
|
||||||
|
if (STR_EQ(property_name, "running")) {
|
||||||
|
return g_variant_new_boolean(status.running);
|
||||||
|
} else {
|
||||||
|
LOG_W("Unknown property!\n");
|
||||||
|
*error = g_error_new(G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_PROPERTY, "Unknown property");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean dbus_cb_dunst_Properties_Set(GDBusConnection *connection,
|
||||||
|
const gchar *sender,
|
||||||
|
const gchar *object_path,
|
||||||
|
const gchar *interface_name,
|
||||||
|
const gchar *property_name,
|
||||||
|
GVariant *value,
|
||||||
|
GError **error,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
if (STR_EQ(property_name, "running")) {
|
||||||
|
dunst_status(S_RUNNING, g_variant_get_boolean(value));
|
||||||
|
wake_up();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
*error = g_error_new(G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_PROPERTY, "Unknown property");
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static const GDBusInterfaceVTable interface_vtable_fdn = {
|
||||||
|
dbus_cb_fdn_methods
|
||||||
|
};
|
||||||
|
|
||||||
|
static const GDBusInterfaceVTable interface_vtable_dunst = {
|
||||||
|
dbus_cb_dunst_methods,
|
||||||
|
dbus_cb_dunst_Properties_Get,
|
||||||
|
dbus_cb_dunst_Properties_Set,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void dbus_cb_bus_acquired(GDBusConnection *connection,
|
static void dbus_cb_bus_acquired(GDBusConnection *connection,
|
||||||
const gchar *name,
|
const gchar *name,
|
||||||
gpointer user_data)
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
guint registration_id;
|
|
||||||
|
|
||||||
GError *err = NULL;
|
GError *err = NULL;
|
||||||
|
if(!g_dbus_connection_register_object(
|
||||||
|
connection,
|
||||||
|
FDN_PATH,
|
||||||
|
introspection_data->interfaces[0],
|
||||||
|
&interface_vtable_fdn,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
&err)) {
|
||||||
|
DIE("Unable to register dbus connection interface '%s': %s", introspection_data->interfaces[0]->name, err->message);
|
||||||
|
}
|
||||||
|
|
||||||
registration_id = g_dbus_connection_register_object(connection,
|
if(!g_dbus_connection_register_object(
|
||||||
FDN_PATH,
|
connection,
|
||||||
introspection_data->interfaces[0],
|
FDN_PATH,
|
||||||
&interface_vtable,
|
introspection_data->interfaces[1],
|
||||||
NULL,
|
&interface_vtable_dunst,
|
||||||
NULL,
|
NULL,
|
||||||
&err);
|
NULL,
|
||||||
|
&err)) {
|
||||||
if (registration_id == 0) {
|
DIE("Unable to register dbus connection interface '%s': %s", introspection_data->interfaces[1]->name, err->message);
|
||||||
DIE("Unable to register dbus connection: %s", err->message);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -449,7 +660,9 @@ static void dbus_cb_name_acquired(GDBusConnection *connection,
|
|||||||
const gchar *name,
|
const gchar *name,
|
||||||
gpointer user_data)
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
dbus_conn = connection;
|
// If we're not able to get org.fd.N bus, we've still got a problem
|
||||||
|
if (STR_EQ(name, FDN_NAME))
|
||||||
|
dbus_conn = connection;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
#ifndef DUNST_DBUS_H
|
#ifndef DUNST_DBUS_H
|
||||||
#define DUNST_DBUS_H
|
#define DUNST_DBUS_H
|
||||||
|
|
||||||
|
#include "dunst.h"
|
||||||
#include "notification.h"
|
#include "notification.h"
|
||||||
|
|
||||||
/// The reasons according to the notification spec
|
/// The reasons according to the notification spec
|
||||||
|
@ -799,6 +799,12 @@ TEST assert_methodlists_sorted(void)
|
|||||||
methods_fdn[i+1].method_name));
|
methods_fdn[i+1].method_name));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i+1 < G_N_ELEMENTS(methods_dunst); i++) {
|
||||||
|
ASSERT(0 > strcmp(
|
||||||
|
methods_dunst[i].method_name,
|
||||||
|
methods_dunst[i+1].method_name));
|
||||||
|
}
|
||||||
|
|
||||||
PASS();
|
PASS();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,15 @@
|
|||||||
|
#define dbus_signal_status_changed(status) signal_sent_stub(status)
|
||||||
#include "../src/dunst.c"
|
#include "../src/dunst.c"
|
||||||
#include "greatest.h"
|
#include "greatest.h"
|
||||||
|
|
||||||
|
static bool signal_sent = false;
|
||||||
|
|
||||||
|
void signal_sent_stub(struct dunst_status status)
|
||||||
|
{
|
||||||
|
signal_sent = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
TEST test_dunst_status(void)
|
TEST test_dunst_status(void)
|
||||||
{
|
{
|
||||||
status = (struct dunst_status) {false, false, false};
|
status = (struct dunst_status) {false, false, false};
|
||||||
|
@ -9,10 +9,12 @@ make -C "${BASE}" SYSTEMD=1 SERVICEDIR_SYSTEMD="${PREFIX}/systemd" SERVICEDIR_DB
|
|||||||
|
|
||||||
diff -u <(find "${PREFIX}" -type f -printf "%P\n" | sort) - <<EOF
|
diff -u <(find "${PREFIX}" -type f -printf "%P\n" | sort) - <<EOF
|
||||||
bin/dunst
|
bin/dunst
|
||||||
|
bin/dunstctl
|
||||||
bin/dunstify
|
bin/dunstify
|
||||||
dbus/org.knopwob.dunst.service
|
dbus/org.knopwob.dunst.service
|
||||||
share/dunst/dunstrc
|
share/dunst/dunstrc
|
||||||
share/man/man1/dunst.1
|
share/man/man1/dunst.1
|
||||||
|
share/man/man1/dunstctl.1
|
||||||
systemd/dunst.service
|
systemd/dunst.service
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user