Merge branch 'important-hint' into 'main'
Add `important` hint See merge request Librem5/feedbackd!116
This commit is contained in:
@@ -115,7 +115,8 @@ You can add your own themes in multiple ways:
|
|||||||
gsettings reset org.sigxcpu.feedbackd theme
|
gsettings reset org.sigxcpu.feedbackd theme
|
||||||
|
|
||||||
Note that you can name your theme as you wish but avoid theme names
|
Note that you can name your theme as you wish but avoid theme names
|
||||||
starting with `__` or `$` as this namespace is reserved.
|
starting with `__` or `$` as this namespace is reserved. This is the
|
||||||
|
preferred way to specify a custom theme.
|
||||||
|
|
||||||
4. By adding your theme file to one of the folders in the `XDG_DATA_DIRS`
|
4. By adding your theme file to one of the folders in the `XDG_DATA_DIRS`
|
||||||
environment variable, appended with `feedbackd/themes/`. This folder isn't
|
environment variable, appended with `feedbackd/themes/`. This folder isn't
|
||||||
|
|||||||
+18
-5
@@ -1,5 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2020 Purism SPC
|
* Copyright (C) 2020 Purism SPC
|
||||||
|
* 2023-2024 The Phosh Developers
|
||||||
|
*
|
||||||
* SPDX-License-Identifier: GPL-3.0+
|
* SPDX-License-Identifier: GPL-3.0+
|
||||||
* Author: Guido Günther <agx@sigxcpu.org>
|
* Author: Guido Günther <agx@sigxcpu.org>
|
||||||
*/
|
*/
|
||||||
@@ -58,7 +60,7 @@ on_user_input (GIOChannel *channel, GIOCondition cond, LfbEvent *event)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
trigger_event (const char *name, const gchar *profile, gint timeout)
|
trigger_event (const char *name, const gchar *profile, gboolean important, gint timeout)
|
||||||
{
|
{
|
||||||
g_autoptr(GError) err = NULL;
|
g_autoptr(GError) err = NULL;
|
||||||
g_autoptr(LfbEvent) event = NULL;
|
g_autoptr(LfbEvent) event = NULL;
|
||||||
@@ -74,6 +76,9 @@ trigger_event (const char *name, const gchar *profile, gint timeout)
|
|||||||
if (profile)
|
if (profile)
|
||||||
lfb_event_set_feedback_profile (event, profile);
|
lfb_event_set_feedback_profile (event, profile);
|
||||||
|
|
||||||
|
if (important)
|
||||||
|
lfb_event_set_important (event, TRUE);
|
||||||
|
|
||||||
g_signal_connect (event, "feedback-ended", (GCallback)on_feedback_ended, &success);
|
g_signal_connect (event, "feedback-ended", (GCallback)on_feedback_ended, &success);
|
||||||
if (!lfb_event_trigger_feedback (event, &err)) {
|
if (!lfb_event_trigger_feedback (event, &err)) {
|
||||||
g_print ("Failed to report event: %s\n", err->message);
|
g_print ("Failed to report event: %s\n", err->message);
|
||||||
@@ -130,20 +135,25 @@ main (int argc, char *argv[0])
|
|||||||
{
|
{
|
||||||
g_autoptr(GOptionContext) opt_context = NULL;
|
g_autoptr(GOptionContext) opt_context = NULL;
|
||||||
g_autoptr(GError) err = NULL;
|
g_autoptr(GError) err = NULL;
|
||||||
g_autofree gchar *profile = NULL;
|
g_autofree char *profile = NULL;
|
||||||
|
g_autofree char *app_id = NULL;
|
||||||
const char *name = NULL;
|
const char *name = NULL;
|
||||||
gboolean success;
|
gboolean success, important = FALSE;
|
||||||
int watch = 30;
|
int watch = 30;
|
||||||
int timeout = -1;
|
int timeout = -1;
|
||||||
const GOptionEntry options [] = {
|
const GOptionEntry options [] = {
|
||||||
{"event", 'E', 0, G_OPTION_ARG_STRING, &name,
|
{"event", 'E', 0, G_OPTION_ARG_STRING, &name,
|
||||||
"Event name. (default: " DEFAULT_EVENT ").", NULL},
|
"Event name. (default: " DEFAULT_EVENT ").", NULL},
|
||||||
|
{"important", 'I', 0, G_OPTION_ARG_NONE, &important,
|
||||||
|
"Whether to set the important hint", NULL},
|
||||||
{"timeout", 't', 0, G_OPTION_ARG_INT, &timeout,
|
{"timeout", 't', 0, G_OPTION_ARG_INT, &timeout,
|
||||||
"Run feedback for timeout seconds", NULL},
|
"Run feedback for timeout seconds", NULL},
|
||||||
{"profile", 'P', 0, G_OPTION_ARG_STRING, &profile,
|
{"profile", 'P', 0, G_OPTION_ARG_STRING, &profile,
|
||||||
"Profile name to set", NULL},
|
"Profile name to set", NULL},
|
||||||
{"watch", 'w', 0, G_OPTION_ARG_INT, &watch,
|
{"watch", 'w', 0, G_OPTION_ARG_INT, &watch,
|
||||||
"How long to watch for feedback longest", NULL},
|
"How long to watch for feedback longest", NULL},
|
||||||
|
{"app-id", 'A', 0, G_OPTION_ARG_STRING, &app_id,
|
||||||
|
"Override used application id"},
|
||||||
{ NULL, 0, 0, G_OPTION_ARG_NONE, NULL, NULL, NULL }
|
{ NULL, 0, 0, G_OPTION_ARG_NONE, NULL, NULL, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -155,7 +165,10 @@ main (int argc, char *argv[0])
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!lfb_init ("org.sigxcpu.fbcli", &err)) {
|
if (!app_id)
|
||||||
|
app_id = g_strdup ("org.sigxcpu.fbcli");
|
||||||
|
|
||||||
|
if (!lfb_init (app_id, &err)) {
|
||||||
g_print ("Failed to init libfeedback: %s\n", err->message);
|
g_print ("Failed to init libfeedback: %s\n", err->message);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -167,7 +180,7 @@ main (int argc, char *argv[0])
|
|||||||
name = g_strdup (DEFAULT_EVENT);
|
name = g_strdup (DEFAULT_EVENT);
|
||||||
|
|
||||||
g_timeout_add_seconds (watch, (GSourceFunc)on_watch_expired, NULL);
|
g_timeout_add_seconds (watch, (GSourceFunc)on_watch_expired, NULL);
|
||||||
success = trigger_event (name, profile, timeout);
|
success = trigger_event (name, profile, important, timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
lfb_uninit ();
|
lfb_uninit ();
|
||||||
|
|||||||
@@ -24,6 +24,12 @@ compiled = gnome.compile_schemas(
|
|||||||
build_by_default: true
|
build_by_default: true
|
||||||
)
|
)
|
||||||
|
|
||||||
|
compile_schemas = find_program('glib-compile-schemas', required: false)
|
||||||
|
if compile_schemas.found()
|
||||||
|
test('Validate schema file', compile_schemas,
|
||||||
|
args: ['--strict', '--dry-run', meson.current_source_dir()])
|
||||||
|
endif
|
||||||
|
|
||||||
install_data(
|
install_data(
|
||||||
schemas,
|
schemas,
|
||||||
install_dir: 'share/glib-2.0/schemas'
|
install_dir: 'share/glib-2.0/schemas'
|
||||||
|
|||||||
@@ -20,7 +20,12 @@
|
|||||||
TriggerFeedback:
|
TriggerFeedback:
|
||||||
@app_id: The application id usually in "reverse DNS" format
|
@app_id: The application id usually in "reverse DNS" format
|
||||||
@event: The event name from the Event naming spec
|
@event: The event name from the Event naming spec
|
||||||
@hints: Additional hints (e.g. to prefer haptic feedback over audio feedback on button press events)
|
@hints: Additional hints. Currently known hints
|
||||||
|
- profile: Override the profile used for this event with the given profile name
|
||||||
|
- important: Override the current global feedback level.
|
||||||
|
Together with the 'profile' hint this allows to trigger feedback for events
|
||||||
|
that would otherwise be disabled. A typical use case is an alarm clock. Note
|
||||||
|
that the feedback daemon (depending on it's configuration) might ignore this flag.
|
||||||
@timeout: When the feedbacks for this event should end latest in seconds. The special values '-1' (just run each feedback once) and '0' (endless loop) are also supported.
|
@timeout: When the feedbacks for this event should end latest in seconds. The special values '-1' (just run each feedback once) and '0' (endless loop) are also supported.
|
||||||
@id: Event id for future reference
|
@id: Event id for future reference
|
||||||
|
|
||||||
|
|||||||
@@ -23,6 +23,15 @@
|
|||||||
feedbackd receives an event.
|
feedbackd receives an event.
|
||||||
</description>
|
</description>
|
||||||
</key>
|
</key>
|
||||||
|
|
||||||
|
<key name="allow-important" type="as">
|
||||||
|
<default>[]</default>
|
||||||
|
<summary>List of apps that can override the feedback level</summary>
|
||||||
|
<description>
|
||||||
|
Apps listed here can override the configured feedack level by
|
||||||
|
setting the 'important' hint on the submitted event.
|
||||||
|
</description>
|
||||||
|
</key>
|
||||||
</schema>
|
</schema>
|
||||||
|
|
||||||
<schema id="org.sigxcpu.feedbackd.application">
|
<schema id="org.sigxcpu.feedbackd.application">
|
||||||
|
|||||||
Vendored
+2
-1
@@ -8,8 +8,9 @@ Build-Depends:
|
|||||||
dh-sequence-gir,
|
dh-sequence-gir,
|
||||||
gsettings-desktop-schemas <!nocheck>,
|
gsettings-desktop-schemas <!nocheck>,
|
||||||
gi-docgen <!nodoc>,
|
gi-docgen <!nodoc>,
|
||||||
|
gir1.2-gio-2.0-dev <!nogir>,
|
||||||
json-glib-tools,
|
json-glib-tools,
|
||||||
libgirepository1.0-dev,
|
libgirepository1.0-dev <!nogir>,
|
||||||
libglib2.0-dev,
|
libglib2.0-dev,
|
||||||
libgudev-1.0-dev,
|
libgudev-1.0-dev,
|
||||||
libgsound-dev,
|
libgsound-dev,
|
||||||
|
|||||||
Vendored
+2
@@ -9,12 +9,14 @@ libfeedback-0.0.so.0 libfeedback-0.0-0 #MINVER#
|
|||||||
lfb_event_get_end_reason@LIBFEEDBACK_0_0_0 0.1.1
|
lfb_event_get_end_reason@LIBFEEDBACK_0_0_0 0.1.1
|
||||||
lfb_event_get_event@LIBFEEDBACK_0_0_0 0.1.1
|
lfb_event_get_event@LIBFEEDBACK_0_0_0 0.1.1
|
||||||
lfb_event_get_feedback_profile@LIBFEEDBACK_0_0_0 0.1.1
|
lfb_event_get_feedback_profile@LIBFEEDBACK_0_0_0 0.1.1
|
||||||
|
lfb_event_get_important@LIBFEEDBACK_0_0_0 0.2.1
|
||||||
lfb_event_get_state@LIBFEEDBACK_0_0_0 0.1.1
|
lfb_event_get_state@LIBFEEDBACK_0_0_0 0.1.1
|
||||||
lfb_event_get_timeout@LIBFEEDBACK_0_0_0 0.1.1
|
lfb_event_get_timeout@LIBFEEDBACK_0_0_0 0.1.1
|
||||||
lfb_event_get_type@LIBFEEDBACK_0_0_0 0.1.1
|
lfb_event_get_type@LIBFEEDBACK_0_0_0 0.1.1
|
||||||
lfb_event_new@LIBFEEDBACK_0_0_0 0.1.1
|
lfb_event_new@LIBFEEDBACK_0_0_0 0.1.1
|
||||||
lfb_event_set_app_id@LIBFEEDBACK_0_0_0 0.2.0
|
lfb_event_set_app_id@LIBFEEDBACK_0_0_0 0.2.0
|
||||||
lfb_event_set_feedback_profile@LIBFEEDBACK_0_0_0 0.1.1
|
lfb_event_set_feedback_profile@LIBFEEDBACK_0_0_0 0.1.1
|
||||||
|
lfb_event_set_important@LIBFEEDBACK_0_0_0 0.2.1
|
||||||
lfb_event_set_timeout@LIBFEEDBACK_0_0_0 0.1.1
|
lfb_event_set_timeout@LIBFEEDBACK_0_0_0 0.1.1
|
||||||
lfb_event_state_get_type@LIBFEEDBACK_0_0_0 0.1.1
|
lfb_event_state_get_type@LIBFEEDBACK_0_0_0 0.1.1
|
||||||
lfb_event_trigger_feedback@LIBFEEDBACK_0_0_0 0.1.1
|
lfb_event_trigger_feedback@LIBFEEDBACK_0_0_0 0.1.1
|
||||||
|
|||||||
@@ -79,6 +79,7 @@ enum {
|
|||||||
PROP_STATE,
|
PROP_STATE,
|
||||||
PROP_END_REASON,
|
PROP_END_REASON,
|
||||||
PROP_FEEDBACK_PROFILE,
|
PROP_FEEDBACK_PROFILE,
|
||||||
|
PROP_IMPORTANT,
|
||||||
PROP_APP_ID,
|
PROP_APP_ID,
|
||||||
PROP_LAST_PROP,
|
PROP_LAST_PROP,
|
||||||
};
|
};
|
||||||
@@ -96,6 +97,7 @@ typedef struct _LfbEvent {
|
|||||||
char *event;
|
char *event;
|
||||||
gint timeout;
|
gint timeout;
|
||||||
gchar *profile;
|
gchar *profile;
|
||||||
|
gboolean important;
|
||||||
char *app_id;
|
char *app_id;
|
||||||
|
|
||||||
guint id;
|
guint id;
|
||||||
@@ -139,6 +141,8 @@ build_hints (LfbEvent *self)
|
|||||||
g_variant_builder_init (&hints_builder, G_VARIANT_TYPE ("a{sv}"));
|
g_variant_builder_init (&hints_builder, G_VARIANT_TYPE ("a{sv}"));
|
||||||
if (self->profile)
|
if (self->profile)
|
||||||
g_variant_builder_add (&hints_builder, "{sv}", "profile", g_variant_new_string (self->profile));
|
g_variant_builder_add (&hints_builder, "{sv}", "profile", g_variant_new_string (self->profile));
|
||||||
|
if (self->important)
|
||||||
|
g_variant_builder_add (&hints_builder, "{sv}", "important", g_variant_new_boolean (self->important));
|
||||||
return g_variant_builder_end (&hints_builder);
|
return g_variant_builder_end (&hints_builder);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -223,6 +227,9 @@ lfb_event_set_property (GObject *object,
|
|||||||
case PROP_FEEDBACK_PROFILE:
|
case PROP_FEEDBACK_PROFILE:
|
||||||
lfb_event_set_feedback_profile (self, g_value_get_string (value));
|
lfb_event_set_feedback_profile (self, g_value_get_string (value));
|
||||||
break;
|
break;
|
||||||
|
case PROP_IMPORTANT:
|
||||||
|
lfb_event_set_important (self, g_value_get_boolean (value));
|
||||||
|
break;
|
||||||
case PROP_APP_ID:
|
case PROP_APP_ID:
|
||||||
lfb_event_set_app_id (self, g_value_get_string (value));
|
lfb_event_set_app_id (self, g_value_get_string (value));
|
||||||
break;
|
break;
|
||||||
@@ -251,6 +258,9 @@ lfb_event_get_property (GObject *object,
|
|||||||
case PROP_FEEDBACK_PROFILE:
|
case PROP_FEEDBACK_PROFILE:
|
||||||
g_value_set_string (value, lfb_event_get_feedback_profile (self));
|
g_value_set_string (value, lfb_event_get_feedback_profile (self));
|
||||||
break;
|
break;
|
||||||
|
case PROP_IMPORTANT:
|
||||||
|
g_value_set_boolean (value, lfb_event_get_important (self));
|
||||||
|
break;
|
||||||
case PROP_APP_ID:
|
case PROP_APP_ID:
|
||||||
g_value_set_string (value, lfb_event_get_app_id (self));
|
g_value_set_string (value, lfb_event_get_app_id (self));
|
||||||
break;
|
break;
|
||||||
@@ -345,6 +355,20 @@ lfb_event_class_init (LfbEventClass *klass)
|
|||||||
NULL,
|
NULL,
|
||||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
|
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* LfbEvent:important:
|
||||||
|
*
|
||||||
|
* Whether to flag this event as important.
|
||||||
|
* [method@LfbEvent.set_imporant] for details.
|
||||||
|
*/
|
||||||
|
props[PROP_IMPORTANT] =
|
||||||
|
g_param_spec_boolean (
|
||||||
|
"important",
|
||||||
|
"Important",
|
||||||
|
"Whether to flags this event as important",
|
||||||
|
FALSE,
|
||||||
|
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* LfbEvent:app-id:
|
* LfbEvent:app-id:
|
||||||
*
|
*
|
||||||
@@ -757,6 +781,44 @@ lfb_event_get_feedback_profile (LfbEvent *self)
|
|||||||
return self->profile;
|
return self->profile;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* lfb_event_set_important:
|
||||||
|
* @self: The event
|
||||||
|
* @important: Whether to flag this event as important
|
||||||
|
*
|
||||||
|
* Tells the feedback server that the sender deems this to be an
|
||||||
|
* important event. A feedback server might allow the sender to
|
||||||
|
* override the current feedback level when this is set.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
lfb_event_set_important (LfbEvent *self, gboolean important)
|
||||||
|
{
|
||||||
|
g_return_if_fail (LFB_IS_EVENT (self));
|
||||||
|
|
||||||
|
if (self->important == important)
|
||||||
|
return;
|
||||||
|
|
||||||
|
self->important = important;
|
||||||
|
g_object_notify_by_pspec (G_OBJECT (self), props[PROP_IMPORTANT]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* lfb_event_get_important:
|
||||||
|
* @self: The event
|
||||||
|
*
|
||||||
|
* Gets the set feedback profile. If no profile was set it returns
|
||||||
|
* %NULL. The event uses the system wide profile in this case.
|
||||||
|
*
|
||||||
|
* Returns: The set feedback profile to use for this event or %NULL.
|
||||||
|
*/
|
||||||
|
gboolean
|
||||||
|
lfb_event_get_important (LfbEvent *self)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (LFB_IS_EVENT (self), FALSE);
|
||||||
|
|
||||||
|
return self->important;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* lfb_event_set_app_id:
|
* lfb_event_set_app_id:
|
||||||
* @self: The event
|
* @self: The event
|
||||||
|
|||||||
@@ -75,9 +75,12 @@ void lfb_event_set_timeout (LfbEvent *self, gint timeout);
|
|||||||
gint lfb_event_get_timeout (LfbEvent *self);
|
gint lfb_event_get_timeout (LfbEvent *self);
|
||||||
void lfb_event_set_feedback_profile (LfbEvent *self, const char *profile);
|
void lfb_event_set_feedback_profile (LfbEvent *self, const char *profile);
|
||||||
const char *lfb_event_get_feedback_profile (LfbEvent *self);
|
const char *lfb_event_get_feedback_profile (LfbEvent *self);
|
||||||
|
void lfb_event_set_important (LfbEvent *self, gboolean important);
|
||||||
|
gboolean lfb_event_get_important (LfbEvent *self);
|
||||||
void lfb_event_set_app_id (LfbEvent *self, const char *app_id);
|
void lfb_event_set_app_id (LfbEvent *self, const char *app_id);
|
||||||
const char *lfb_event_get_app_id (LfbEvent *self);
|
const char *lfb_event_get_app_id (LfbEvent *self);
|
||||||
const char *lfb_event_get_event (LfbEvent *self);
|
const char *lfb_event_get_event (LfbEvent *self);
|
||||||
|
|
||||||
LfbEventState lfb_event_get_state (LfbEvent *self);
|
LfbEventState lfb_event_get_state (LfbEvent *self);
|
||||||
LfbEventEndReason lfb_event_get_end_reason (LfbEvent *self);
|
LfbEventEndReason lfb_event_get_end_reason (LfbEvent *self);
|
||||||
|
|
||||||
|
|||||||
@@ -26,6 +26,7 @@
|
|||||||
#define FEEDBACKD_SCHEMA_ID "org.sigxcpu.feedbackd"
|
#define FEEDBACKD_SCHEMA_ID "org.sigxcpu.feedbackd"
|
||||||
#define FEEDBACKD_KEY_PROFILE "profile"
|
#define FEEDBACKD_KEY_PROFILE "profile"
|
||||||
#define FEEDBACKD_KEY_THEME "theme"
|
#define FEEDBACKD_KEY_THEME "theme"
|
||||||
|
#define FEEDBACKD_KEY_ALLOW_IMPORTANT "allow-important"
|
||||||
|
|
||||||
#define APP_SCHEMA FEEDBACKD_SCHEMA_ID ".application"
|
#define APP_SCHEMA FEEDBACKD_SCHEMA_ID ".application"
|
||||||
#define APP_PREFIX "/org/sigxcpu/feedbackd/application/"
|
#define APP_PREFIX "/org/sigxcpu/feedbackd/application/"
|
||||||
@@ -48,6 +49,7 @@ typedef struct _FbdFeedbackManager {
|
|||||||
FbdFeedbackProfileLevel level;
|
FbdFeedbackProfileLevel level;
|
||||||
FbdFeedbackTheme *theme;
|
FbdFeedbackTheme *theme;
|
||||||
guint next_id;
|
guint next_id;
|
||||||
|
GStrv allow_important;
|
||||||
|
|
||||||
/* Key: event id, value: event */
|
/* Key: event id, value: event */
|
||||||
GHashTable *events;
|
GHashTable *events;
|
||||||
@@ -225,6 +227,33 @@ on_feedbackd_setting_changed (FbdFeedbackManager *self,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
app_is_important (FbdFeedbackManager *self, const char *app_id)
|
||||||
|
{
|
||||||
|
if (!self->allow_important)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (g_strv_contains ((const char *const *)self->allow_important, app_id))
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_feedbackd_allow_important_changed (FbdFeedbackManager *self,
|
||||||
|
const gchar *key,
|
||||||
|
GSettings *settings)
|
||||||
|
{
|
||||||
|
g_return_if_fail (FBD_IS_FEEDBACK_MANAGER (self));
|
||||||
|
g_return_if_fail (G_IS_SETTINGS (settings));
|
||||||
|
|
||||||
|
g_strfreev (self->allow_important);
|
||||||
|
self->allow_important = g_settings_get_strv(self->settings, FEEDBACKD_KEY_ALLOW_IMPORTANT);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
on_client_vanished (GDBusConnection *connection,
|
on_client_vanished (GDBusConnection *connection,
|
||||||
const gchar *name,
|
const gchar *name,
|
||||||
@@ -298,24 +327,31 @@ get_max_level (FbdFeedbackProfileLevel global_level,
|
|||||||
{
|
{
|
||||||
FbdFeedbackProfileLevel level;
|
FbdFeedbackProfileLevel level;
|
||||||
|
|
||||||
/* Individual events and apps can select lower levels than the global level but not higher ones */
|
/* Per app configuration can only select a *lower* feedback level */
|
||||||
level = global_level > app_level ? app_level : global_level;
|
level = MIN (global_level, app_level);
|
||||||
level = level > event_level ? event_level : level;
|
/* A hint in an event can only select a *lower* feedback level */
|
||||||
|
level = MIN (level, event_level);
|
||||||
|
|
||||||
return level;
|
return level;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
parse_hints (GVariant *hints, FbdFeedbackProfileLevel *level)
|
parse_hints (GVariant *hints, FbdFeedbackProfileLevel *level, gboolean *hint_important)
|
||||||
{
|
{
|
||||||
const gchar *profile;
|
const gchar *profile;
|
||||||
gboolean found;
|
gboolean found, important;
|
||||||
g_auto (GVariantDict) dict = G_VARIANT_DICT_INIT (NULL);
|
g_auto (GVariantDict) dict = G_VARIANT_DICT_INIT (NULL);
|
||||||
|
|
||||||
g_variant_dict_init (&dict, hints);
|
g_variant_dict_init (&dict, hints);
|
||||||
found = g_variant_dict_lookup (&dict, "profile", "&s", &profile);
|
|
||||||
|
|
||||||
|
found = g_variant_dict_lookup (&dict, "profile", "&s", &profile);
|
||||||
if (level && found)
|
if (level && found)
|
||||||
*level = fbd_feedback_profile_level (profile);
|
*level = fbd_feedback_profile_level (profile);
|
||||||
|
|
||||||
|
found = g_variant_dict_lookup (&dict, "important", "b", &important);
|
||||||
|
if (hint_important && found)
|
||||||
|
*hint_important = important;
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -334,6 +370,7 @@ fbd_feedback_manager_handle_trigger_feedback (LfbGdbusFeedback *object,
|
|||||||
const gchar *sender;
|
const gchar *sender;
|
||||||
FbdFeedbackProfileLevel app_level, level, hint_level = FBD_FEEDBACK_PROFILE_LEVEL_FULL;
|
FbdFeedbackProfileLevel app_level, level, hint_level = FBD_FEEDBACK_PROFILE_LEVEL_FULL;
|
||||||
gboolean found_fb = FALSE;
|
gboolean found_fb = FALSE;
|
||||||
|
gboolean hint_important = FALSE, can_important;
|
||||||
|
|
||||||
sender = g_dbus_method_invocation_get_sender (invocation);
|
sender = g_dbus_method_invocation_get_sender (invocation);
|
||||||
g_debug ("Event '%s' for '%s' from %s", arg_event, arg_app_id, sender);
|
g_debug ("Event '%s' for '%s' from %s", arg_event, arg_app_id, sender);
|
||||||
@@ -357,7 +394,7 @@ fbd_feedback_manager_handle_trigger_feedback (LfbGdbusFeedback *object,
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!parse_hints (arg_hints, &hint_level)) {
|
if (!parse_hints (arg_hints, &hint_level, &hint_important)) {
|
||||||
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
||||||
G_DBUS_ERROR_INVALID_ARGS,
|
G_DBUS_ERROR_INVALID_ARGS,
|
||||||
"Invalid hints");
|
"Invalid hints");
|
||||||
@@ -373,7 +410,12 @@ fbd_feedback_manager_handle_trigger_feedback (LfbGdbusFeedback *object,
|
|||||||
g_hash_table_insert (self->events, GUINT_TO_POINTER (event_id), event);
|
g_hash_table_insert (self->events, GUINT_TO_POINTER (event_id), event);
|
||||||
|
|
||||||
app_level = app_get_feedback_level (arg_app_id);
|
app_level = app_get_feedback_level (arg_app_id);
|
||||||
level = get_max_level (self->level, app_level, hint_level);
|
can_important = app_is_important (self, arg_app_id);
|
||||||
|
|
||||||
|
if (hint_important && can_important)
|
||||||
|
level = hint_level;
|
||||||
|
else
|
||||||
|
level = get_max_level (self->level, app_level, hint_level);
|
||||||
|
|
||||||
feedbacks = fbd_feedback_theme_lookup_feedback (self->theme, level, event);
|
feedbacks = fbd_feedback_theme_lookup_feedback (self->theme, level, event);
|
||||||
if (feedbacks) {
|
if (feedbacks) {
|
||||||
@@ -453,8 +495,13 @@ fbd_feedback_manager_constructed (GObject *object)
|
|||||||
g_signal_connect_swapped (self->settings, "changed::" FEEDBACKD_KEY_PROFILE,
|
g_signal_connect_swapped (self->settings, "changed::" FEEDBACKD_KEY_PROFILE,
|
||||||
G_CALLBACK (on_feedbackd_setting_changed), self);
|
G_CALLBACK (on_feedbackd_setting_changed), self);
|
||||||
on_feedbackd_setting_changed (self, FEEDBACKD_KEY_PROFILE, self->settings);
|
on_feedbackd_setting_changed (self, FEEDBACKD_KEY_PROFILE, self->settings);
|
||||||
|
|
||||||
|
g_signal_connect_swapped (self->settings, "changed::" FEEDBACKD_KEY_ALLOW_IMPORTANT,
|
||||||
|
G_CALLBACK (on_feedbackd_allow_important_changed), self);
|
||||||
|
on_feedbackd_allow_important_changed (self, FEEDBACKD_KEY_ALLOW_IMPORTANT, self->settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
fbd_feedback_manager_dispose (GObject *object)
|
fbd_feedback_manager_dispose (GObject *object)
|
||||||
{
|
{
|
||||||
@@ -466,6 +513,8 @@ fbd_feedback_manager_dispose (GObject *object)
|
|||||||
g_clear_object (&self->vibra);
|
g_clear_object (&self->vibra);
|
||||||
g_clear_object (&self->leds);
|
g_clear_object (&self->leds);
|
||||||
g_clear_object (&self->client);
|
g_clear_object (&self->client);
|
||||||
|
|
||||||
|
g_clear_pointer (&self->allow_important, g_strfreev);
|
||||||
g_clear_pointer (&self->events, g_hash_table_destroy);
|
g_clear_pointer (&self->events, g_hash_table_destroy);
|
||||||
g_clear_pointer (&self->clients, g_hash_table_destroy);
|
g_clear_pointer (&self->clients, g_hash_table_destroy);
|
||||||
|
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ test_lfb_event_props (void)
|
|||||||
g_autofree gchar *evname = NULL;
|
g_autofree gchar *evname = NULL;
|
||||||
g_autofree gchar *profile = NULL;
|
g_autofree gchar *profile = NULL;
|
||||||
g_autofree gchar *app_id = NULL;
|
g_autofree gchar *app_id = NULL;
|
||||||
|
gboolean important;
|
||||||
gint timeout;
|
gint timeout;
|
||||||
|
|
||||||
g_assert_true (lfb_init (TEST_APP_ID, NULL));
|
g_assert_true (lfb_init (TEST_APP_ID, NULL));
|
||||||
@@ -27,10 +28,12 @@ test_lfb_event_props (void)
|
|||||||
"timeout", &timeout,
|
"timeout", &timeout,
|
||||||
"feedback-profile", &profile,
|
"feedback-profile", &profile,
|
||||||
"app-id", &app_id,
|
"app-id", &app_id,
|
||||||
|
"important", &important,
|
||||||
NULL);
|
NULL);
|
||||||
g_assert_cmpstr (evname, ==, "window-close");
|
g_assert_cmpstr (evname, ==, "window-close");
|
||||||
g_assert_cmpint (timeout, ==, -1);
|
g_assert_cmpint (timeout, ==, -1);
|
||||||
g_assert_null (profile);
|
g_assert_null (profile);
|
||||||
|
g_assert_false (important);
|
||||||
g_assert_null (app_id);
|
g_assert_null (app_id);
|
||||||
|
|
||||||
g_assert_cmpint (lfb_event_get_end_reason (event), ==, LFB_EVENT_END_REASON_NATURAL);
|
g_assert_cmpint (lfb_event_get_end_reason (event), ==, LFB_EVENT_END_REASON_NATURAL);
|
||||||
|
|||||||
@@ -238,6 +238,7 @@ test_lfb_integration_event_async (void)
|
|||||||
lfb_event_set_timeout (event10, 1);
|
lfb_event_set_timeout (event10, 1);
|
||||||
g_assert_cmpint (lfb_event_get_timeout (event10), ==, 1);
|
g_assert_cmpint (lfb_event_get_timeout (event10), ==, 1);
|
||||||
lfb_event_set_feedback_profile (event10, "quiet");
|
lfb_event_set_feedback_profile (event10, "quiet");
|
||||||
|
lfb_event_set_important (event10, FALSE);
|
||||||
g_signal_connect (event10, "feedback-ended", (GCallback)on_feedback_ended, &cmp1);
|
g_signal_connect (event10, "feedback-ended", (GCallback)on_feedback_ended, &cmp1);
|
||||||
|
|
||||||
/* The async callback ends the main loop */
|
/* The async callback ends the main loop */
|
||||||
|
|||||||
Reference in New Issue
Block a user