ASSERT_STREQ(vc.keymap, "ru");
}
+TEST(x11_context_normalize) {
+ _cleanup_(x11_context_clear) X11Context xc = {};
+
+ /* x11_read_data() parses 'Option "XkbVariant" ""' into a non-NULL
+ * empty string. x11_context_normalize() converts empty strings back
+ * to NULL (with freeing), so that x11_context_is_safe() and
+ * x11_context_equal() treat them as unset. See issue #43007. */
+
+ /* Empty fields are normalized to NULL. */
+ ASSERT_OK(free_and_strdup(&xc.layout, "gb"));
+ ASSERT_OK(free_and_strdup(&xc.variant, ""));
+ ASSERT_OK(free_and_strdup(&xc.options, ""));
+ x11_context_normalize(&xc);
+ ASSERT_STREQ(xc.layout, "gb");
+ ASSERT_NULL(xc.variant);
+ ASSERT_NULL(xc.options);
+ ASSERT_TRUE(x11_context_is_safe(&xc));
+ ASSERT_OK(x11_context_verify(&xc));
+
+ /* An empty layout leaves the context empty, not unsafe. */
+ x11_context_clear(&xc);
+ ASSERT_OK(free_and_strdup(&xc.layout, ""));
+ x11_context_normalize(&xc);
+ ASSERT_NULL(xc.layout);
+ ASSERT_TRUE(x11_context_isempty(&xc));
+}
+
static int intro(void) {
_cleanup_free_ char *map = NULL;
xc->options = empty_to_null(xc->options);
}
+static char* empty_to_null_and_free(char *p) {
+ return isempty(p) ? mfree(p) : p;
+}
+
+void x11_context_normalize(X11Context *xc) {
+ assert(xc);
+
+ /* Like x11_context_empty_to_null(), but also frees the heap memory
+ * owned by the fields. Use this for contexts whose strings are
+ * heap-allocated (e.g. x11_read_data()), not for borrowed contexts
+ * such as the one built by method_set_x11_keyboard() from a D-Bus
+ * message. */
+
+ xc->layout = empty_to_null_and_free(xc->layout);
+ xc->model = empty_to_null_and_free(xc->model);
+ xc->variant = empty_to_null_and_free(xc->variant);
+ xc->options = empty_to_null_and_free(xc->options);
+}
+
bool x11_context_is_safe(const X11Context *xc) {
assert(xc);
void x11_context_replace(X11Context *dest, X11Context *src);
bool x11_context_isempty(const X11Context *xc);
void x11_context_empty_to_null(X11Context *xc);
+void x11_context_normalize(X11Context *xc);
bool x11_context_is_safe(const X11Context *xc);
bool x11_context_equal(const X11Context *a, const X11Context *b);
int x11_context_copy(X11Context *dest, const X11Context *src);