Marco Trevisan (Treviño) has proposed merging
~3v1n0/ubuntu/+source/mutter:ubuntu/master into
~ubuntu-desktop/ubuntu/+source/mutter:ubuntu/master.
Requested reviews:
Ubuntu Desktop (ubuntu-desktop)
For more details, see:
https://code.launchpad.net/~3v1n0/ubuntu/+source/mutter/+git/mutter/+merge/374693
--
Your team Ubuntu Desktop is requested to review the proposed merge of
~3v1n0/ubuntu/+source/mutter:ubuntu/master into
~ubuntu-desktop/ubuntu/+source/mutter:ubuntu/master.
diff --git a/clutter/clutter/clutter-actor-private.h b/clutter/clutter/clutter-actor-private.h
index 119ec42..fa2d4c3 100644
--- a/clutter/clutter/clutter-actor-private.h
+++ b/clutter/clutter/clutter-actor-private.h
@@ -274,6 +274,9 @@ void _clutter_actor_set_enable_paint_unmapped
void _clutter_actor_set_has_pointer (ClutterActor *self,
gboolean has_pointer);
+void _clutter_actor_set_has_key_focus (ClutterActor *self,
+ gboolean has_key_focus);
+
void _clutter_actor_queue_redraw_with_clip (ClutterActor *self,
ClutterRedrawFlags flags,
const ClutterPaintVolume *clip_volume);
diff --git a/clutter/clutter/clutter-actor.c b/clutter/clutter/clutter-actor.c
index e763291..ecf9a59 100644
--- a/clutter/clutter/clutter-actor.c
+++ b/clutter/clutter/clutter-actor.c
@@ -835,6 +835,7 @@ struct _ClutterActorPrivate
guint enable_model_view_transform : 1;
guint enable_paint_unmapped : 1;
guint has_pointer : 1;
+ guint has_key_focus : 1;
guint propagated_one_redraw : 1;
guint paint_volume_valid : 1;
guint last_paint_volume_valid : 1;
@@ -1692,6 +1693,20 @@ clutter_actor_is_mapped (ClutterActor *self)
}
static void
+maybe_unset_key_focus (ClutterActor *self)
+{
+ ClutterActor *stage;
+
+ if (!self->priv->has_key_focus)
+ return;
+
+ stage = _clutter_actor_get_stage_internal (self);
+
+ if (stage)
+ clutter_stage_set_key_focus (CLUTTER_STAGE (stage), NULL);
+}
+
+static void
clutter_actor_real_unmap (ClutterActor *self)
{
ClutterActorPrivate *priv = self->priv;
@@ -1724,17 +1739,7 @@ clutter_actor_real_unmap (ClutterActor *self)
/* relinquish keyboard focus if we were unmapped while owning it */
if (!CLUTTER_ACTOR_IS_TOPLEVEL (self))
- {
- ClutterStage *stage;
-
- stage = CLUTTER_STAGE (_clutter_actor_get_stage_internal (self));
-
- if (stage != NULL &&
- clutter_stage_get_key_focus (stage) == self)
- {
- clutter_stage_set_key_focus (stage, NULL);
- }
- }
+ maybe_unset_key_focus (self);
}
/**
@@ -6064,6 +6069,8 @@ clutter_actor_dispose (GObject *object)
object->ref_count,
g_type_name (G_OBJECT_TYPE (self)));
+ maybe_unset_key_focus (self);
+
/* Stop the emission of any property change */
g_object_freeze_notify (object);
@@ -15979,6 +15986,9 @@ clutter_actor_grab_key_focus (ClutterActor *self)
g_return_if_fail (CLUTTER_IS_ACTOR (self));
+ if (self->priv->has_key_focus)
+ return;
+
stage = _clutter_actor_get_stage_internal (self);
if (stage != NULL)
clutter_stage_set_key_focus (CLUTTER_STAGE (stage), self);
@@ -16768,6 +16778,23 @@ _clutter_actor_set_has_pointer (ClutterActor *self,
}
}
+void
+_clutter_actor_set_has_key_focus (ClutterActor *self,
+ gboolean has_key_focus)
+{
+ ClutterActorPrivate *priv = self->priv;
+
+ if (priv->has_key_focus != has_key_focus)
+ {
+ priv->has_key_focus = has_key_focus;
+
+ if (has_key_focus)
+ g_signal_emit (self, actor_signals[KEY_FOCUS_IN], 0);
+ else
+ g_signal_emit (self, actor_signals[KEY_FOCUS_OUT], 0);
+ }
+}
+
/**
* clutter_actor_get_text_direction:
* @self: a #ClutterActor
@@ -17616,15 +17643,9 @@ clutter_actor_clear_effects (ClutterActor *self)
gboolean
clutter_actor_has_key_focus (ClutterActor *self)
{
- ClutterActor *stage;
-
g_return_val_if_fail (CLUTTER_IS_ACTOR (self), FALSE);
- stage = _clutter_actor_get_stage_internal (self);
- if (stage == NULL)
- return FALSE;
-
- return clutter_stage_get_key_focus (CLUTTER_STAGE (stage)) == self;
+ return self->priv->has_key_focus;
}
static gboolean
diff --git a/clutter/clutter/clutter-shader-effect.c b/clutter/clutter/clutter-shader-effect.c
index a5ae1ee..c659dab 100644
--- a/clutter/clutter/clutter-shader-effect.c
+++ b/clutter/clutter/clutter-shader-effect.c
@@ -500,6 +500,7 @@ static void
clutter_shader_effect_init (ClutterShaderEffect *effect)
{
effect->priv = clutter_shader_effect_get_instance_private (effect);
+ effect->priv->shader_type = CLUTTER_FRAGMENT_SHADER;
}
/**
diff --git a/clutter/clutter/clutter-stage.c b/clutter/clutter/clutter-stage.c
index 245cb89..c4b88b3 100644
--- a/clutter/clutter/clutter-stage.c
+++ b/clutter/clutter/clutter-stage.c
@@ -1066,10 +1066,7 @@ clutter_stage_emit_key_focus_event (ClutterStage *stage,
if (priv->key_focused_actor == NULL)
return;
- if (focus_in)
- g_signal_emit_by_name (priv->key_focused_actor, "key-focus-in");
- else
- g_signal_emit_by_name (priv->key_focused_actor, "key-focus-out");
+ _clutter_actor_set_has_key_focus (CLUTTER_ACTOR (stage), focus_in);
g_object_notify_by_pspec (G_OBJECT (stage), obj_props[PROP_KEY_FOCUS]);
}
@@ -3011,14 +3008,6 @@ clutter_stage_get_title (ClutterStage *stage)
return stage->priv->title;
}
-static void
-on_key_focus_destroy (ClutterActor *actor,
- ClutterStage *stage)
-{
- /* unset the key focus */
- clutter_stage_set_key_focus (stage, NULL);
-}
-
/**
* clutter_stage_set_key_focus:
* @stage: the #ClutterStage
@@ -3058,18 +3047,14 @@ clutter_stage_set_key_focus (ClutterStage *stage,
old_focused_actor = priv->key_focused_actor;
/* set key_focused_actor to NULL before emitting the signal or someone
- * might hide the previously focused actor in the signal handler and we'd
- * get re-entrant call and get glib critical from g_object_weak_unref
+ * might hide the previously focused actor in the signal handler
*/
- g_signal_handlers_disconnect_by_func (priv->key_focused_actor,
- G_CALLBACK (on_key_focus_destroy),
- stage);
priv->key_focused_actor = NULL;
- g_signal_emit_by_name (old_focused_actor, "key-focus-out");
+ _clutter_actor_set_has_key_focus (old_focused_actor, FALSE);
}
else
- g_signal_emit_by_name (stage, "key-focus-out");
+ _clutter_actor_set_has_key_focus (CLUTTER_ACTOR (stage), FALSE);
/* Note, if someone changes key focus in focus-out signal handler we'd be
* overriding the latter call below moving the focus where it was originally
@@ -3079,14 +3064,10 @@ clutter_stage_set_key_focus (ClutterStage *stage,
if (actor != NULL)
{
priv->key_focused_actor = actor;
-
- g_signal_connect (actor,
- "destroy", G_CALLBACK (on_key_focus_destroy),
- stage);
- g_signal_emit_by_name (priv->key_focused_actor, "key-focus-in");
+ _clutter_actor_set_has_key_focus (actor, TRUE);
}
else
- g_signal_emit_by_name (stage, "key-focus-in");
+ _clutter_actor_set_has_key_focus (CLUTTER_ACTOR (stage), TRUE);
g_object_notify_by_pspec (G_OBJECT (stage), obj_props[PROP_KEY_FOCUS]);
}
diff --git a/cogl/cogl-pango/meson.build b/cogl/cogl-pango/meson.build
index 787ec01..06fba51 100644
--- a/cogl/cogl-pango/meson.build
+++ b/cogl/cogl-pango/meson.build
@@ -62,7 +62,7 @@ if have_introspection
],
extra_args: introspection_args + [
'-UCOGL_COMPILATION',
- '-DG_LOG_DOMAIN=\"CoglPango\"',
+ '-DG_LOG_DOMAIN="CoglPango"',
],
install_dir_gir: pkglibdir,
install_dir_typelib: pkglibdir,
diff --git a/debian/changelog b/debian/changelog
index 06847be..2515499 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,34 @@
+mutter (3.34.1+git20191022-1ubuntu19.10.1) UNRELEASED; urgency=medium
+
+ * Merge with debian. Remaining changes:
+ + debian/control:
+ - Update VCS flags to point to launchpad
+ - Update maintainer to ubuntu
+ + debian/gbp.conf: update branch to point to ubuntu/master
+ + debian/patches/x11-Add-support-for-fractional-scaling-using-Randr.patch:
+ - X11: Add support for fractional scaling using Randr
+
+ -- Marco Trevisan (Treviño) <[email protected]> Thu, 24 Oct 2019 03:28:30 +0200
+
+mutter (3.34.1+git20191022-1) unstable; urgency=medium
+
+ * New upstream snapshot release
+ + Fix night mode in wayland session (LP: #1847551)
+ + Don't emit key-focus-out events on destroyed actors (LP: #1848119)
+ + Fix an headers syntax error (LP: #1841709)
+ + backends: Update inhibited state for the monitor and respect that state
+ + clutter-backend-x11: Don't push keymap events to clutter
+ + Fix drag and drop for applications in wayland
+ + Avoid X11 roundtrips on underscanning checks
+
+ -- Marco Trevisan (Treviño) <[email protected]> Wed, 23 Oct 2019 10:53:23 +0100
+
+mutter (3.34.1-3) unstable; urgency=medium
+
+ * Bump meson test timeout multiplier from 4 to 6 for armel
+
+ -- Jeremy Bicha <[email protected]> Sun, 20 Oct 2019 22:48:29 -0400
+
mutter (3.34.1-1ubuntu1) eoan; urgency=medium
* Merge with debian. Remaining changes:
diff --git a/debian/rules b/debian/rules
index ce960f4..0a6150b 100755
--- a/debian/rules
+++ b/debian/rules
@@ -61,7 +61,7 @@ TEST_COMMAND_BASE=env \
XDG_RUNTIME_DIR=$(BUILDDIR)/XRD \
GSETTINGS_SCHEMA_DIR=$(BUILDDIR)/data \
dbus-run-session -- xvfb-run -s '+iglx -noreset' -a \
- meson test -C $(BUILDDIR) --no-rebuild --verbose --timeout-multiplier 4 \
+ meson test -C $(BUILDDIR) --no-rebuild --verbose --timeout-multiplier 6 \
--no-stdsplit --print-errorlogs
TEST_COMMAND=$(TEST_COMMAND_BASE) --no-suite flaky
TEST_COMMAND_FLAKY=$(TEST_COMMAND_BASE) --suite flaky
diff --git a/debian/watch b/debian/watch
index 35b7b17..d8c6911 100644
--- a/debian/watch
+++ b/debian/watch
@@ -1,3 +1,3 @@
version=4
-https://download.gnome.org/sources/@PACKAGE@/([\d\.]+)/ \
- @PACKAGE@@ANY_VERSION@\.tar\.xz
+https://download.gnome.org/sources/@PACKAGE@/([\d\.]+[02468])/ \
+ @PACKAGE@@ANY_VERSION@@ARCHIVE_EXT@
diff --git a/src/backends/meta-dbus-session-watcher.c b/src/backends/meta-dbus-session-watcher.c
index 22718e6..a885b42 100644
--- a/src/backends/meta-dbus-session-watcher.c
+++ b/src/backends/meta-dbus-session-watcher.c
@@ -214,6 +214,8 @@ meta_dbus_session_watcher_finalize (GObject *object)
MetaDbusSessionWatcher *session_watcher = META_DBUS_SESSION_WATCHER (object);
g_hash_table_destroy (session_watcher->clients);
+
+ G_OBJECT_CLASS (meta_dbus_session_watcher_parent_class)->finalize (object);
}
static void
diff --git a/src/backends/meta-idle-monitor.c b/src/backends/meta-idle-monitor.c
index 9fa4817..2ff1602 100644
--- a/src/backends/meta-idle-monitor.c
+++ b/src/backends/meta-idle-monitor.c
@@ -207,6 +207,8 @@ update_inhibited (MetaIdleMonitor *monitor,
if (inhibited == monitor->inhibited)
return;
+ monitor->inhibited = inhibited;
+
g_hash_table_foreach (monitor->watches,
update_inhibited_watch,
monitor);
@@ -516,9 +518,16 @@ meta_idle_monitor_reset_idletime (MetaIdleMonitor *monitor)
}
else
{
- g_source_set_ready_time (watch->timeout_source,
- monitor->last_event_time +
- watch->timeout_msec * 1000);
+ if (monitor->inhibited)
+ {
+ g_source_set_ready_time (watch->timeout_source, -1);
+ }
+ else
+ {
+ g_source_set_ready_time (watch->timeout_source,
+ monitor->last_event_time +
+ watch->timeout_msec * 1000);
+ }
}
}
diff --git a/src/backends/meta-monitor-manager.c b/src/backends/meta-monitor-manager.c
index 41036ca..0210aee 100644
--- a/src/backends/meta-monitor-manager.c
+++ b/src/backends/meta-monitor-manager.c
@@ -1648,6 +1648,7 @@ create_monitor_config_from_variant (MetaMonitorManager *manager,
MetaMonitorModeSpec *monitor_mode_spec;
g_autoptr (GVariant) properties_variant = NULL;
gboolean enable_underscanning = FALSE;
+ gboolean set_underscanning = FALSE;
g_variant_get (monitor_config_variant, "(ss@a{sv})",
&connector,
@@ -1670,7 +1671,18 @@ create_monitor_config_from_variant (MetaMonitorManager *manager,
return NULL;
}
- g_variant_lookup (properties_variant, "underscanning", "b", &enable_underscanning);
+ set_underscanning =
+ g_variant_lookup (properties_variant, "underscanning", "b",
+ &enable_underscanning);
+ if (set_underscanning)
+ {
+ if (enable_underscanning && !meta_monitor_supports_underscanning (monitor))
+ {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ "Underscanning requested but unsupported");
+ return NULL;
+ }
+ }
monitor_spec = meta_monitor_spec_clone (meta_monitor_get_spec (monitor));
diff --git a/src/backends/native/meta-kms-crtc.c b/src/backends/native/meta-kms-crtc.c
index 3610df9..da99a58 100644
--- a/src/backends/native/meta-kms-crtc.c
+++ b/src/backends/native/meta-kms-crtc.c
@@ -143,14 +143,26 @@ meta_kms_crtc_update_state (MetaKmsCrtc *crtc)
drmModeFreeCrtc (drm_crtc);
}
+static void
+clear_gamma_state (MetaKmsCrtc *crtc)
+{
+ crtc->current_state.gamma.size = 0;
+ g_clear_pointer (&crtc->current_state.gamma.red, g_free);
+ g_clear_pointer (&crtc->current_state.gamma.green, g_free);
+ g_clear_pointer (&crtc->current_state.gamma.blue, g_free);
+}
+
void
meta_kms_crtc_predict_state (MetaKmsCrtc *crtc,
MetaKmsUpdate *update)
{
+ gboolean is_gamma_valid;
GList *mode_sets;
GList *crtc_gammas;
GList *l;
+ is_gamma_valid = TRUE;
+
mode_sets = meta_kms_update_get_mode_sets (update);
for (l = mode_sets; l; l = l->next)
{
@@ -178,6 +190,8 @@ meta_kms_crtc_predict_state (MetaKmsCrtc *crtc,
crtc->current_state.drm_mode = (drmModeModeInfo) { 0 };
}
+ is_gamma_valid = FALSE;
+
break;
}
@@ -196,8 +210,36 @@ meta_kms_crtc_predict_state (MetaKmsCrtc *crtc,
g_memdup (gamma->green, gamma->size * sizeof (uint16_t));
crtc->current_state.gamma.blue =
g_memdup (gamma->blue, gamma->size * sizeof (uint16_t));
+
+ is_gamma_valid = TRUE;
break;
}
+
+ if (!is_gamma_valid)
+ {
+ if (crtc->current_state.is_drm_mode_valid)
+ {
+ MetaKmsImplDevice *impl_device;
+ drmModeCrtc *drm_crtc;
+
+ impl_device = meta_kms_device_get_impl_device (crtc->device);
+ drm_crtc = drmModeGetCrtc (meta_kms_impl_device_get_fd (impl_device),
+ crtc->id);
+ if (drm_crtc)
+ {
+ read_gamma_state (crtc, impl_device, drm_crtc);
+ drmModeFreeCrtc (drm_crtc);
+ }
+ else
+ {
+ clear_gamma_state (crtc);
+ }
+ }
+ else
+ {
+ clear_gamma_state (crtc);
+ }
+ }
}
MetaKmsCrtc *
@@ -220,9 +262,7 @@ meta_kms_crtc_finalize (GObject *object)
{
MetaKmsCrtc *crtc = META_KMS_CRTC (object);
- g_clear_pointer (&crtc->current_state.gamma.red, g_free);
- g_clear_pointer (&crtc->current_state.gamma.green, g_free);
- g_clear_pointer (&crtc->current_state.gamma.blue, g_free);
+ clear_gamma_state (crtc);
G_OBJECT_CLASS (meta_kms_crtc_parent_class)->finalize (object);
}
diff --git a/src/backends/native/meta-kms-update-private.h b/src/backends/native/meta-kms-update-private.h
index 88e2590..df7737c 100644
--- a/src/backends/native/meta-kms-update-private.h
+++ b/src/backends/native/meta-kms-update-private.h
@@ -110,6 +110,4 @@ GList * meta_kms_update_get_connector_properties (MetaKmsUpdate *update);
GList * meta_kms_update_get_crtc_gammas (MetaKmsUpdate *update);
-gboolean meta_kms_update_has_mode_set (MetaKmsUpdate *update);
-
#endif /* META_KMS_UPDATE_PRIVATE_H */
diff --git a/src/backends/native/meta-kms-update.c b/src/backends/native/meta-kms-update.c
index 2a4a05c..c946aa7 100644
--- a/src/backends/native/meta-kms-update.c
+++ b/src/backends/native/meta-kms-update.c
@@ -282,12 +282,6 @@ meta_kms_update_get_crtc_gammas (MetaKmsUpdate *update)
return update->crtc_gammas;
}
-gboolean
-meta_kms_update_has_mode_set (MetaKmsUpdate *update)
-{
- return !!update->mode_sets;
-}
-
void
meta_kms_update_seal (MetaKmsUpdate *update)
{
diff --git a/src/backends/native/meta-kms.c b/src/backends/native/meta-kms.c
index 9485bb4..804a1ad 100644
--- a/src/backends/native/meta-kms.c
+++ b/src/backends/native/meta-kms.c
@@ -211,8 +211,7 @@ meta_kms_update_process_in_impl (MetaKmsImpl *impl,
ret = meta_kms_impl_process_update (impl, update, error);
- if (meta_kms_update_has_mode_set (update))
- meta_kms_predict_states_in_impl (meta_kms_impl_get_kms (impl), update);
+ meta_kms_predict_states_in_impl (meta_kms_impl_get_kms (impl), update);
return ret;
}
diff --git a/src/backends/x11/meta-clutter-backend-x11.c b/src/backends/x11/meta-clutter-backend-x11.c
index 8d4b64b..b6334de 100644
--- a/src/backends/x11/meta-clutter-backend-x11.c
+++ b/src/backends/x11/meta-clutter-backend-x11.c
@@ -129,7 +129,7 @@ meta_clutter_backend_x11_translate_event (ClutterBackend *backend,
return TRUE;
if (meta_keymap_x11_handle_event (backend_x11->keymap, native))
- return TRUE;
+ return FALSE;
stage_x11 = META_STAGE_X11 (clutter_backend_get_stage_window (backend));
if (meta_stage_x11_translate_event (stage_x11, native, event))
diff --git a/src/backends/x11/meta-event-x11.c b/src/backends/x11/meta-event-x11.c
index 8b4f4fc..19da223 100644
--- a/src/backends/x11/meta-event-x11.c
+++ b/src/backends/x11/meta-event-x11.c
@@ -82,12 +82,12 @@ meta_x11_handle_event (XEvent *xevent)
gboolean allocated_event;
/* The return values here are someone approximate; we return
- * META_X11_FILTER_REMOVE if a clutter event is
+ * CLUTTER_X11_FILTER_REMOVE if a clutter event is
* generated for the event. This mostly, but not entirely,
* corresponds to whether other event processing should be
* excluded. As long as the stage window is not shared with another
* toolkit it should be safe, and never return
- * %META_X11_FILTER_REMOVE when more processing is needed.
+ * %CLUTTER_X11_FILTER_REMOVE when more processing is needed.
*/
result = CLUTTER_X11_FILTER_CONTINUE;
diff --git a/src/compositor/meta-window-actor.c b/src/compositor/meta-window-actor.c
index db9ccec..fd99844 100644
--- a/src/compositor/meta-window-actor.c
+++ b/src/compositor/meta-window-actor.c
@@ -2183,21 +2183,25 @@ meta_window_actor_get_image (MetaWindowActor *self,
if (clutter_actor_get_n_children (actor) == 1)
{
MetaShapedTexture *stex;
- MetaRectangle surface_clip;
- int geometry_scale;
+ MetaRectangle *surface_clip = NULL;
- geometry_scale =
- meta_window_actor_get_geometry_scale (self);
+ if (clip)
+ {
- surface_clip = (MetaRectangle) {
- .x = clip->x / geometry_scale,
- .y = clip->y / geometry_scale,
- .width = clip->width / geometry_scale,
- .height = clip->height / geometry_scale,
- };
+ int geometry_scale;
+
+ geometry_scale =
+ meta_window_actor_get_geometry_scale (self);
+
+ surface_clip = g_alloca (sizeof (MetaRectangle));
+ surface_clip->x = clip->x / geometry_scale,
+ surface_clip->y = clip->y / geometry_scale;
+ surface_clip->width = clip->width / geometry_scale;
+ surface_clip->height = clip->height / geometry_scale;
+ }
stex = meta_surface_actor_get_texture (priv->surface);
- return meta_shaped_texture_get_image (stex, &surface_clip);
+ return meta_shaped_texture_get_image (stex, surface_clip);
}
clutter_actor_get_size (actor, &width, &height);
diff --git a/src/core/main.c b/src/core/main.c
index 7f4f666..3935f35 100644
--- a/src/core/main.c
+++ b/src/core/main.c
@@ -766,6 +766,6 @@ meta_test_init (void)
close (fd);
#else
- g_error ("Tests require wayland support");
+ g_warning ("Tests require wayland support");
#endif
}
diff --git a/src/core/meta-selection-source-memory.c b/src/core/meta-selection-source-memory.c
index 04b7f39..c8b0c83 100644
--- a/src/core/meta-selection-source-memory.c
+++ b/src/core/meta-selection-source-memory.c
@@ -76,6 +76,9 @@ meta_selection_source_memory_get_mimetypes (MetaSelectionSource *source)
{
MetaSelectionSourceMemory *source_mem = META_SELECTION_SOURCE_MEMORY (source);
+ if (!source_mem->mimetype)
+ return NULL;
+
return g_list_prepend (NULL, g_strdup (source_mem->mimetype));
}
@@ -84,7 +87,7 @@ meta_selection_source_memory_finalize (GObject *object)
{
MetaSelectionSourceMemory *source_mem = META_SELECTION_SOURCE_MEMORY (object);
- g_bytes_unref (source_mem->content);
+ g_clear_pointer (&source_mem->content, g_bytes_unref);
g_free (source_mem->mimetype);
G_OBJECT_CLASS (meta_selection_source_memory_parent_class)->finalize (object);
diff --git a/src/wayland/meta-selection-source-wayland-private.h b/src/wayland/meta-selection-source-wayland-private.h
index 6affc77..a6ada88 100644
--- a/src/wayland/meta-selection-source-wayland-private.h
+++ b/src/wayland/meta-selection-source-wayland-private.h
@@ -25,6 +25,8 @@
#include <wayland-server.h>
#include "meta/meta-selection-source.h"
+#include "wayland/meta-wayland-data-device.h"
+#include "wayland/meta-wayland-data-device-private.h"
#define META_TYPE_SELECTION_SOURCE_WAYLAND (meta_selection_source_wayland_get_type ())
@@ -33,14 +35,6 @@ G_DECLARE_FINAL_TYPE (MetaSelectionSourceWayland,
META, SELECTION_SOURCE_WAYLAND,
MetaSelectionSource)
-typedef void (* MetaWaylandSendFunc) (struct wl_resource *resource,
- const char *mimetype,
- int fd);
-typedef void (* MetaWaylandCancelFunc) (struct wl_resource *resource);
-
-MetaSelectionSource * meta_selection_source_wayland_new (struct wl_resource *resource,
- GList *mime_types,
- MetaWaylandSendFunc send_func,
- MetaWaylandCancelFunc cancel_func);
+MetaSelectionSource * meta_selection_source_wayland_new (MetaWaylandDataSource *source);
#endif /* META_SELECTION_SOURCE_WAYLAND_H */
diff --git a/src/wayland/meta-selection-source-wayland.c b/src/wayland/meta-selection-source-wayland.c
index 7031c91..4f6f0c3 100644
--- a/src/wayland/meta-selection-source-wayland.c
+++ b/src/wayland/meta-selection-source-wayland.c
@@ -29,10 +29,8 @@
struct _MetaSelectionSourceWayland
{
MetaSelectionSource parent_instance;
+ MetaWaylandDataSource *data_source;
GList *mimetypes;
- MetaWaylandSendFunc send_func;
- MetaWaylandCancelFunc cancel_func;
- struct wl_resource *resource;
};
G_DEFINE_TYPE (MetaSelectionSourceWayland, meta_selection_source_wayland,
@@ -85,7 +83,8 @@ meta_selection_source_wayland_read_async (MetaSelectionSource *source,
g_task_set_source_tag (task, meta_selection_source_wayland_read_async);
stream = g_unix_input_stream_new (pipe_fds[0], TRUE);
- source_wayland->send_func (source_wayland->resource, mimetype, pipe_fds[1]);
+ meta_wayland_data_source_send (source_wayland->data_source,
+ mimetype, pipe_fds[1]);
close (pipe_fds[1]);
g_task_return_pointer (task, stream, g_object_unref);
@@ -119,7 +118,7 @@ meta_selection_source_wayland_deactivated (MetaSelectionSource *source)
MetaSelectionSourceWayland *source_wayland =
META_SELECTION_SOURCE_WAYLAND (source);
- source_wayland->cancel_func (source_wayland->resource);
+ meta_wayland_data_source_cancel (source_wayland->data_source);
META_SELECTION_SOURCE_CLASS (meta_selection_source_wayland_parent_class)->deactivated (source);
}
@@ -143,20 +142,29 @@ meta_selection_source_wayland_init (MetaSelectionSourceWayland *source)
{
}
+static GList *
+copy_string_array_to_list (struct wl_array *array)
+{
+ GList *l = NULL;
+ char **p;
+
+ wl_array_for_each (p, array)
+ l = g_list_prepend (l, g_strdup (*p));
+
+ return l;
+}
+
MetaSelectionSource *
-meta_selection_source_wayland_new (struct wl_resource *resource,
- GList *mime_types,
- MetaWaylandSendFunc send_func,
- MetaWaylandCancelFunc cancel_func)
+meta_selection_source_wayland_new (MetaWaylandDataSource *data_source)
{
MetaSelectionSourceWayland *source_wayland;
+ struct wl_array *mimetypes;
source_wayland = g_object_new (META_TYPE_SELECTION_SOURCE_WAYLAND, NULL);
- source_wayland->mimetypes = g_list_copy_deep (mime_types,
- (GCopyFunc) g_strdup, NULL);
- source_wayland->send_func = send_func;
- source_wayland->cancel_func = cancel_func;
- source_wayland->resource = resource;
+ source_wayland->data_source = data_source;
+
+ mimetypes = meta_wayland_data_source_get_mime_types (data_source);
+ source_wayland->mimetypes = copy_string_array_to_list (mimetypes);
return META_SELECTION_SOURCE (source_wayland);
}
diff --git a/src/wayland/meta-wayland-actor-surface.c b/src/wayland/meta-wayland-actor-surface.c
index f74bfc5..a61a80e 100644
--- a/src/wayland/meta-wayland-actor-surface.c
+++ b/src/wayland/meta-wayland-actor-surface.c
@@ -241,6 +241,11 @@ meta_wayland_actor_surface_commit (MetaWaylandSurfaceRole *surface_role,
if (!priv->actor)
return;
+ if (!wl_list_empty (&pending->frame_callback_list) &&
+ cairo_region_is_empty (pending->surface_damage) &&
+ cairo_region_is_empty (pending->buffer_damage))
+ clutter_actor_queue_redraw (CLUTTER_ACTOR (priv->actor));
+
meta_wayland_actor_surface_queue_frame_callbacks (actor_surface, pending);
meta_wayland_actor_surface_sync_actor_state (actor_surface);
diff --git a/src/wayland/meta-wayland-data-device.c b/src/wayland/meta-wayland-data-device.c
index 2ca77e8..38aa0f3 100644
--- a/src/wayland/meta-wayland-data-device.c
+++ b/src/wayland/meta-wayland-data-device.c
@@ -36,6 +36,7 @@
#include <unistd.h>
#include "compositor/meta-dnd-actor-private.h"
+#include "meta/meta-selection-source-memory.h"
#include "wayland/meta-selection-source-wayland-private.h"
#include "wayland/meta-wayland-dnd-surface.h"
#include "wayland/meta-wayland-pointer.h"
@@ -59,6 +60,7 @@ struct _MetaWaylandDataOffer
gboolean action_sent;
uint32_t dnd_actions;
enum wl_data_device_manager_dnd_action preferred_dnd_action;
+ MetaSelectionType selection_type;
};
typedef struct _MetaWaylandDataSourcePrivate
@@ -84,8 +86,6 @@ typedef struct _MetaWaylandDataSourceWayland
typedef struct _MetaWaylandDataSourcePrimary
{
MetaWaylandDataSourceWayland parent;
-
- struct wl_resource *resource;
} MetaWaylandDataSourcePrimary;
G_DEFINE_TYPE_WITH_PRIVATE (MetaWaylandDataSource, meta_wayland_data_source,
@@ -252,7 +252,7 @@ meta_wayland_data_source_get_mime_types (const MetaWaylandDataSource *source)
return &priv->mime_types;
}
-static void
+void
meta_wayland_data_source_cancel (MetaWaylandDataSource *source)
{
META_WAYLAND_DATA_SOURCE_GET_CLASS (source)->cancel (source);
@@ -400,11 +400,7 @@ data_offer_receive (struct wl_client *client, struct wl_resource *resource,
GList *mime_types;
gboolean found;
- if (offer->dnd_actions != 0)
- selection_type = META_SELECTION_DND;
- else
- selection_type = META_SELECTION_CLIPBOARD;
-
+ selection_type = offer->selection_type;
mime_types = meta_selection_get_mimetypes (meta_display_get_selection (display),
selection_type);
found = g_list_find_custom (mime_types, mime_type, (GCompareFunc) g_strcmp0) != NULL;
@@ -623,6 +619,7 @@ create_and_send_dnd_offer (MetaWaylandDataSource *source,
MetaWaylandDataOffer *offer = g_slice_new0 (MetaWaylandDataOffer);
char **p;
+ offer->selection_type = META_SELECTION_DND;
offer->source = source;
g_object_add_weak_pointer (G_OBJECT (source), (gpointer *)&offer->source);
offer->resource = wl_resource_create (wl_resource_get_client (target),
@@ -1154,18 +1151,6 @@ destroy_data_device_icon (struct wl_listener *listener, void *data)
clutter_actor_remove_all_children (drag_grab->feedback_actor);
}
-static GList *
-copy_string_array_to_list (struct wl_array *array)
-{
- GList *l = NULL;
- char **p;
-
- wl_array_for_each (p, array)
- l = g_list_prepend (l, g_strdup (*p));
-
- return l;
-}
-
void
meta_wayland_data_device_start_drag (MetaWaylandDataDevice *data_device,
struct wl_client *client,
@@ -1265,7 +1250,6 @@ data_device_start_drag (struct wl_client *client,
MetaWaylandSurface *surface = NULL, *icon_surface = NULL;
MetaWaylandDataSource *drag_source = NULL;
MetaSelectionSource *selection_source;
- GList *mimetypes;
if (origin_resource)
surface = wl_resource_get_user_data (origin_resource);
@@ -1301,14 +1285,10 @@ data_device_start_drag (struct wl_client *client,
return;
}
- mimetypes = copy_string_array_to_list (meta_wayland_data_source_get_mime_types (drag_source));
- selection_source = meta_selection_source_wayland_new (source_resource,
- mimetypes,
- wl_data_source_send_send,
- wl_data_source_send_cancelled);
- g_list_free_full (mimetypes, g_free);
+ selection_source = meta_selection_source_wayland_new (drag_source);
set_selection_source (data_device, META_SELECTION_DND,
selection_source);
+ g_object_unref (selection_source);
meta_wayland_pointer_set_focus (seat->pointer, NULL);
meta_wayland_data_device_start_drag (data_device, client,
@@ -1370,7 +1350,8 @@ meta_wayland_source_cancel (MetaWaylandDataSource *source)
MetaWaylandDataSourceWayland *source_wayland =
META_WAYLAND_DATA_SOURCE_WAYLAND (source);
- wl_data_source_send_cancelled (source_wayland->resource);
+ if (source_wayland->resource)
+ wl_data_source_send_cancelled (source_wayland->resource);
}
static void
@@ -1421,7 +1402,7 @@ meta_wayland_source_drag_finished (MetaWaylandDataSource *source)
static void
meta_wayland_source_finalize (GObject *object)
{
- G_OBJECT_CLASS (meta_wayland_data_source_parent_class)->finalize (object);
+ G_OBJECT_CLASS (meta_wayland_data_source_wayland_parent_class)->finalize (object);
}
static void
@@ -1451,10 +1432,10 @@ meta_wayland_data_source_primary_send (MetaWaylandDataSource *source,
const gchar *mime_type,
gint fd)
{
- MetaWaylandDataSourcePrimary *source_primary;
+ MetaWaylandDataSourceWayland *source_wayland;
- source_primary = META_WAYLAND_DATA_SOURCE_PRIMARY (source);
- gtk_primary_selection_source_send_send (source_primary->resource,
+ source_wayland = META_WAYLAND_DATA_SOURCE_WAYLAND (source);
+ gtk_primary_selection_source_send_send (source_wayland->resource,
mime_type, fd);
close (fd);
}
@@ -1462,10 +1443,11 @@ meta_wayland_data_source_primary_send (MetaWaylandDataSource *source,
static void
meta_wayland_data_source_primary_cancel (MetaWaylandDataSource *source)
{
- MetaWaylandDataSourcePrimary *source_primary;
+ MetaWaylandDataSourceWayland *source_wayland;
- source_primary = META_WAYLAND_DATA_SOURCE_PRIMARY (source);
- gtk_primary_selection_source_send_cancelled (source_primary->resource);
+ source_wayland = META_WAYLAND_DATA_SOURCE_WAYLAND (source);
+ if (source_wayland->resource)
+ gtk_primary_selection_source_send_cancelled (source_wayland->resource);
}
static void
@@ -1644,6 +1626,7 @@ meta_wayland_data_device_set_selection (MetaWaylandDataDevice *data_device,
MetaWaylandSeat *seat = wl_container_of (data_device, seat, data_device);
struct wl_resource *data_device_resource;
struct wl_client *focus_client;
+ MetaSelectionSource *selection_source;
if (data_device->selection_data_source &&
data_device->selection_serial - serial < UINT32_MAX / 2)
@@ -1661,43 +1644,34 @@ meta_wayland_data_device_set_selection (MetaWaylandDataDevice *data_device,
data_device->selection_data_source = source;
data_device->selection_serial = serial;
- focus_client = meta_wayland_keyboard_get_focus_client (seat->keyboard);
- if (focus_client)
- {
- data_device_resource = wl_resource_find_for_client (&data_device->resource_list, focus_client);
- if (data_device_resource)
- {
- struct wl_resource *offer;
- offer = create_and_send_clipboard_offer (data_device, data_device_resource);
- wl_data_device_send_selection (data_device_resource, offer);
- }
- }
-
if (source)
{
- MetaWaylandDataSourceWayland *source_wayland =
- META_WAYLAND_DATA_SOURCE_WAYLAND (source);
- MetaSelectionSource *selection_source;
- GList *mimetypes;
-
meta_wayland_data_source_set_seat (source, seat);
g_object_weak_ref (G_OBJECT (source),
selection_data_source_destroyed,
data_device);
- mimetypes = copy_string_array_to_list (meta_wayland_data_source_get_mime_types (source));
- selection_source = meta_selection_source_wayland_new (source_wayland->resource,
- mimetypes,
- wl_data_source_send_send,
- wl_data_source_send_cancelled);
- g_list_free_full (mimetypes, g_free);
-
- set_selection_source (data_device, META_SELECTION_CLIPBOARD,
- selection_source);
+ selection_source = meta_selection_source_wayland_new (source);
}
else
{
- unset_selection_source (data_device, META_SELECTION_CLIPBOARD);
+ selection_source = g_object_new (META_TYPE_SELECTION_SOURCE_MEMORY, NULL);
+ }
+
+ set_selection_source (data_device, META_SELECTION_CLIPBOARD,
+ selection_source);
+ g_object_unref (selection_source);
+
+ focus_client = meta_wayland_keyboard_get_focus_client (seat->keyboard);
+ if (focus_client)
+ {
+ data_device_resource = wl_resource_find_for_client (&data_device->resource_list, focus_client);
+ if (data_device_resource)
+ {
+ struct wl_resource *offer;
+ offer = create_and_send_clipboard_offer (data_device, data_device_resource);
+ wl_data_device_send_selection (data_device_resource, offer);
+ }
}
wl_signal_emit (&data_device->selection_ownership_signal, source);
@@ -1773,12 +1747,13 @@ meta_wayland_data_device_set_primary (MetaWaylandDataDevice *data_device,
MetaWaylandSeat *seat = wl_container_of (data_device, seat, data_device);
struct wl_resource *data_device_resource;
struct wl_client *focus_client;
+ MetaSelectionSource *selection_source;
if (META_IS_WAYLAND_DATA_SOURCE_PRIMARY (source))
{
struct wl_resource *resource;
- resource = META_WAYLAND_DATA_SOURCE_PRIMARY (source)->resource;
+ resource = META_WAYLAND_DATA_SOURCE_WAYLAND (source)->resource;
if (wl_resource_get_client (resource) !=
meta_wayland_keyboard_get_focus_client (seat->keyboard))
@@ -1800,41 +1775,34 @@ meta_wayland_data_device_set_primary (MetaWaylandDataDevice *data_device,
data_device->primary_data_source = source;
data_device->primary_serial = serial;
- focus_client = meta_wayland_keyboard_get_focus_client (seat->keyboard);
- if (focus_client)
- {
- data_device_resource = wl_resource_find_for_client (&data_device->primary_resource_list, focus_client);
- if (data_device_resource)
- {
- struct wl_resource *offer;
- offer = create_and_send_primary_offer (data_device, data_device_resource);
- gtk_primary_selection_device_send_selection (data_device_resource, offer);
- }
- }
-
if (source)
{
- MetaSelectionSource *selection_source;
- GList *mimetypes;
-
meta_wayland_data_source_set_seat (source, seat);
g_object_weak_ref (G_OBJECT (source),
primary_source_destroyed,
data_device);
- mimetypes = copy_string_array_to_list (meta_wayland_data_source_get_mime_types (source));
- selection_source = meta_selection_source_wayland_new (META_WAYLAND_DATA_SOURCE_PRIMARY (source)->resource,
- mimetypes,
- gtk_primary_selection_source_send_send,
- gtk_primary_selection_source_send_cancelled);
- g_list_free_full (mimetypes, g_free);
-
- set_selection_source (data_device, META_SELECTION_PRIMARY,
- selection_source);
+ selection_source = meta_selection_source_wayland_new (source);
}
else
{
- unset_selection_source (data_device, META_SELECTION_PRIMARY);
+ selection_source = g_object_new (META_TYPE_SELECTION_SOURCE_MEMORY, NULL);
+ }
+
+ set_selection_source (data_device, META_SELECTION_PRIMARY,
+ selection_source);
+ g_object_unref (selection_source);
+
+ focus_client = meta_wayland_keyboard_get_focus_client (seat->keyboard);
+ if (focus_client)
+ {
+ data_device_resource = wl_resource_find_for_client (&data_device->primary_resource_list, focus_client);
+ if (data_device_resource)
+ {
+ struct wl_resource *offer;
+ offer = create_and_send_primary_offer (data_device, data_device_resource);
+ gtk_primary_selection_device_send_selection (data_device_resource, offer);
+ }
}
wl_signal_emit (&data_device->primary_ownership_signal, source);
@@ -1968,7 +1936,7 @@ static const struct wl_data_device_manager_interface manager_interface = {
static void
destroy_primary_source (struct wl_resource *resource)
{
- MetaWaylandDataSourcePrimary *source = wl_resource_get_user_data (resource);
+ MetaWaylandDataSourceWayland *source = wl_resource_get_user_data (resource);
source->resource = NULL;
g_object_unref (source);
@@ -2073,6 +2041,7 @@ create_and_send_clipboard_offer (MetaWaylandDataDevice *data_device,
return NULL;
offer = g_slice_new0 (MetaWaylandDataOffer);
+ offer->selection_type = META_SELECTION_CLIPBOARD;
offer->resource = wl_resource_create (wl_resource_get_client (target),
&wl_data_offer_interface,
wl_resource_get_version (target), 0);
@@ -2105,6 +2074,7 @@ create_and_send_primary_offer (MetaWaylandDataDevice *data_device,
return NULL;
offer = g_slice_new0 (MetaWaylandDataOffer);
+ offer->selection_type = META_SELECTION_PRIMARY;
offer->resource = wl_resource_create (wl_resource_get_client (target),
>k_primary_selection_offer_interface,
wl_resource_get_version (target), 0);
@@ -2204,7 +2174,7 @@ meta_wayland_data_source_wayland_new (struct wl_resource *resource)
static MetaWaylandDataSource *
meta_wayland_data_source_primary_new (struct wl_resource *resource)
{
- MetaWaylandDataSourcePrimary *source_primary =
+ MetaWaylandDataSourceWayland *source_primary =
g_object_new (META_TYPE_WAYLAND_DATA_SOURCE_PRIMARY, NULL);
source_primary->resource = resource;
diff --git a/src/wayland/meta-wayland-data-device.h b/src/wayland/meta-wayland-data-device.h
index 729baac..efa5478 100644
--- a/src/wayland/meta-wayland-data-device.h
+++ b/src/wayland/meta-wayland-data-device.h
@@ -111,6 +111,8 @@ gboolean meta_wayland_data_source_has_target (MetaWaylandDataSource *source)
void meta_wayland_data_source_set_has_target (MetaWaylandDataSource *source,
gboolean has_target);
+void meta_wayland_data_source_cancel (MetaWaylandDataSource *source);
+
void meta_wayland_data_source_send (MetaWaylandDataSource *source,
const gchar *mime_type,
gint fd);
diff --git a/src/wayland/meta-wayland-surface.c b/src/wayland/meta-wayland-surface.c
index 5def3c5..163b7c5 100644
--- a/src/wayland/meta-wayland-surface.c
+++ b/src/wayland/meta-wayland-surface.c
@@ -401,7 +401,7 @@ static void
pending_buffer_resource_destroyed (MetaWaylandBuffer *buffer,
MetaWaylandPendingState *pending)
{
- g_signal_handler_disconnect (buffer, pending->buffer_destroy_handler_id);
+ g_clear_signal_handler (&pending->buffer_destroy_handler_id, buffer);
pending->buffer = NULL;
}
@@ -972,8 +972,12 @@ wl_surface_frame (struct wl_client *client,
callback = g_slice_new0 (MetaWaylandFrameCallback);
callback->surface = surface;
- callback->resource = wl_resource_create (client, &wl_callback_interface, META_WL_CALLBACK_VERSION, callback_id);
- wl_resource_set_implementation (callback->resource, NULL, callback, destroy_frame_callback);
+ callback->resource = wl_resource_create (client,
+ &wl_callback_interface,
+ META_WL_CALLBACK_VERSION,
+ callback_id);
+ wl_resource_set_implementation (callback->resource, NULL, callback,
+ destroy_frame_callback);
wl_list_insert (surface->pending->frame_callback_list.prev, &callback->link);
}
@@ -1370,7 +1374,9 @@ wl_surface_destructor (struct wl_resource *resource)
meta_wayland_compositor_destroy_frame_callbacks (compositor, surface);
- g_hash_table_foreach (surface->outputs_to_destroy_notify_id, surface_output_disconnect_signal, surface);
+ g_hash_table_foreach (surface->outputs_to_destroy_notify_id,
+ surface_output_disconnect_signal,
+ surface);
g_hash_table_unref (surface->outputs_to_destroy_notify_id);
wl_list_for_each_safe (cb, next, &surface->pending_frame_callback_list, link)
@@ -1419,12 +1425,20 @@ meta_wayland_surface_create (MetaWaylandCompositor *compositor,
guint32 id)
{
MetaWaylandSurface *surface = g_object_new (META_TYPE_WAYLAND_SURFACE, NULL);
+ int surface_version;
surface->compositor = compositor;
surface->scale = 1;
- surface->resource = wl_resource_create (client, &wl_surface_interface, wl_resource_get_version (compositor_resource), id);
- wl_resource_set_implementation (surface->resource, &meta_wayland_wl_surface_interface, surface, wl_surface_destructor);
+ surface_version = wl_resource_get_version (compositor_resource);
+ surface->resource = wl_resource_create (client,
+ &wl_surface_interface,
+ surface_version,
+ id);
+ wl_resource_set_implementation (surface->resource,
+ &meta_wayland_wl_surface_interface,
+ surface,
+ wl_surface_destructor);
wl_list_init (&surface->pending_frame_callback_list);
diff --git a/src/x11/meta-selection-source-x11.c b/src/x11/meta-selection-source-x11.c
index 15a7636..55e5003 100644
--- a/src/x11/meta-selection-source-x11.c
+++ b/src/x11/meta-selection-source-x11.c
@@ -82,6 +82,15 @@ meta_selection_source_x11_read_async (MetaSelectionSource *source,
task = g_task_new (source, cancellable, callback, user_data);
g_task_set_source_tag (task, meta_selection_source_x11_read_async);
+ if (strcmp (mimetype, "text/plain") == 0 &&
+ g_list_find_custom (source_x11->mimetypes, "STRING",
+ (GCompareFunc) g_strcmp0))
+ mimetype = "STRING";
+ else if (strcmp (mimetype, "text/plain;charset=utf-8") == 0 &&
+ g_list_find_custom (source_x11->mimetypes, "UTF8_STRING",
+ (GCompareFunc) g_strcmp0))
+ mimetype = "UTF8_STRING";
+
meta_x11_selection_input_stream_new_async (source_x11->x11_display,
source_x11->x11_display->selection.xwindow,
gdk_x11_get_xatom_name (source_x11->xselection),
@@ -139,6 +148,8 @@ atoms_to_mimetypes (MetaX11Display *display,
const Atom *atoms;
gsize size;
guint i, n_atoms;
+ gboolean utf8_string_found = FALSE, utf8_text_plain_found = FALSE;
+ gboolean string_found = FALSE, text_plain_found = FALSE;
atoms = g_bytes_get_data (bytes, &size);
n_atoms = size / sizeof (Atom);
@@ -149,8 +160,19 @@ atoms_to_mimetypes (MetaX11Display *display,
mimetype = gdk_x11_get_xatom_name (atoms[i]);
mimetypes = g_list_prepend (mimetypes, g_strdup (mimetype));
+
+ utf8_text_plain_found |= strcmp (mimetype, "text/plain;charset=utf-8") == 0;
+ text_plain_found |= strcmp (mimetype, "text/plain") == 0;
+ utf8_string_found |= strcmp (mimetype, "UTF8_STRING") == 0;
+ string_found |= strcmp (mimetype, "STRING") == 0;
}
+ /* Ensure non-x11 clients get well-known mimetypes */
+ if (string_found && !text_plain_found)
+ mimetypes = g_list_prepend (mimetypes, g_strdup ("text/plain"));
+ if (utf8_string_found && !utf8_text_plain_found)
+ mimetypes = g_list_prepend (mimetypes, g_strdup ("text/plain;charset=utf-8"));
+
return mimetypes;
}
--
ubuntu-desktop mailing list
[email protected]
https://lists.ubuntu.com/mailman/listinfo/ubuntu-desktop