diff -Nru mutter-3.36.1/clutter/clutter/cally/cally-actor.c mutter-3.36.9/clutter/clutter/cally/cally-actor.c --- mutter-3.36.1/clutter/clutter/cally/cally-actor.c 2020-03-30 19:29:39.045891000 +0000 +++ mutter-3.36.9/clutter/clutter/cally/cally-actor.c 2021-03-15 23:07:33.034507300 +0000 @@ -767,10 +767,11 @@ cally_actor_action_do_action (AtkAction *action, gint index) { - CallyActor *cally_actor = NULL; - AtkStateSet *set = NULL; - CallyActorPrivate *priv = NULL; - CallyActorActionInfo *info = NULL; + CallyActor *cally_actor = NULL; + AtkStateSet *set = NULL; + CallyActorPrivate *priv = NULL; + CallyActorActionInfo *info = NULL; + gboolean did_action = FALSE; cally_actor = CALLY_ACTOR (action); priv = cally_actor->priv; @@ -778,21 +779,19 @@ set = atk_object_ref_state_set (ATK_OBJECT (cally_actor)); if (atk_state_set_contains_state (set, ATK_STATE_DEFUNCT)) - return FALSE; + goto out; if (!atk_state_set_contains_state (set, ATK_STATE_SENSITIVE) || !atk_state_set_contains_state (set, ATK_STATE_SHOWING)) - return FALSE; - - g_object_unref (set); + goto out; info = _cally_actor_get_action_info (cally_actor, index); if (info == NULL) - return FALSE; + goto out; if (info->do_action_func == NULL) - return FALSE; + goto out; if (!priv->action_queue) priv->action_queue = g_queue_new (); @@ -802,7 +801,12 @@ if (!priv->action_idle_handler) priv->action_idle_handler = g_idle_add (idle_do_action, cally_actor); - return TRUE; + did_action = TRUE; + +out: + g_clear_object (&set); + + return did_action; } static gboolean diff -Nru mutter-3.36.1/clutter/clutter/clutter-actor.c mutter-3.36.9/clutter/clutter/clutter-actor.c --- mutter-3.36.1/clutter/clutter/clutter-actor.c 2020-03-30 19:29:39.051890900 +0000 +++ mutter-3.36.9/clutter/clutter/clutter-actor.c 2021-03-15 23:07:33.041507000 +0000 @@ -1138,6 +1138,7 @@ static GQuark quark_touchpad = 0; static GQuark quark_proximity = 0; static GQuark quark_pad = 0; +static GQuark quark_im = 0; G_DEFINE_TYPE_WITH_CODE (ClutterActor, clutter_actor, @@ -2410,6 +2411,7 @@ g_return_val_if_fail (CLUTTER_IS_ACTOR (self), FALSE); if (CLUTTER_ACTOR_IS_MAPPED (self) && + clutter_actor_has_allocation (self) && (_clutter_context_get_pick_mode () == CLUTTER_PICK_ALL || CLUTTER_ACTOR_IS_REACTIVE (self))) return TRUE; @@ -2603,6 +2605,9 @@ gboolean retval; ClutterActorBox old_alloc = { 0, }; + g_return_val_if_fail (!isnan (box->x1) && !isnan (box->x2) && + !isnan (box->y1) && !isnan (box->y2), FALSE); + obj = G_OBJECT (self); g_object_freeze_notify (obj); @@ -4193,7 +4198,9 @@ clutter_paint_node_unref (dummy); /* XXX:2.0 - Call the paint() virtual directly */ - if (g_signal_has_handler_pending (self, actor_signals[PAINT], + if (!(clutter_paint_context_get_paint_flags (paint_context) & + CLUTTER_PAINT_FLAG_NO_PAINT_SIGNAL) && + g_signal_has_handler_pending (self, actor_signals[PAINT], 0, TRUE)) g_signal_emit (self, actor_signals[PAINT], 0, paint_context); else @@ -6575,6 +6582,7 @@ quark_touchpad = g_quark_from_static_string ("touchpad"); quark_proximity = g_quark_from_static_string ("proximity"); quark_pad = g_quark_from_static_string ("pad"); + quark_im = g_quark_from_static_string ("im"); object_class->constructor = clutter_actor_constructor; object_class->set_property = clutter_actor_set_property; @@ -10363,6 +10371,11 @@ old_allocation = priv->allocation; real_allocation = *box; + g_return_if_fail (!isnan (real_allocation.x1) && + !isnan (real_allocation.x2) && + !isnan (real_allocation.y1) && + !isnan (real_allocation.y2)); + /* constraints are allowed to modify the allocation only here; we do * this prior to all the other checks so that we can bail out if the * allocation did not change @@ -13977,6 +13990,14 @@ case CLUTTER_PAD_RING: detail = quark_pad; break; + case CLUTTER_IM_COMMIT: + case CLUTTER_IM_DELETE: + case CLUTTER_IM_PREEDIT: + detail = quark_im; + break; + case CLUTTER_DEVICE_ADDED: + case CLUTTER_DEVICE_REMOVED: + break; case CLUTTER_EVENT_LAST: /* Just keep compiler warnings quiet */ break; } @@ -14030,6 +14051,9 @@ case CLUTTER_DELETE: case CLUTTER_DESTROY_NOTIFY: case CLUTTER_CLIENT_MESSAGE: + case CLUTTER_IM_COMMIT: + case CLUTTER_IM_DELETE: + case CLUTTER_IM_PREEDIT: default: signal_num = -1; break; diff -Nru mutter-3.36.1/clutter/clutter/clutter-box-layout.c mutter-3.36.9/clutter/clutter/clutter-box-layout.c --- mutter-3.36.1/clutter/clutter/clutter-box-layout.c 2020-03-30 19:29:39.063890500 +0000 +++ mutter-3.36.9/clutter/clutter/clutter-box-layout.c 2021-03-15 23:07:33.047506800 +0000 @@ -475,8 +475,10 @@ ClutterActor *child; gint n_children = 0; gfloat minimum, natural; + float largest_min_size, largest_nat_size; minimum = natural = 0; + largest_min_size = largest_nat_size = 0; clutter_actor_iter_init (&iter, container); while (clutter_actor_iter_next (&iter, &child)) @@ -491,8 +493,22 @@ get_child_size (child, priv->orientation, for_size, &child_min, &child_nat); - minimum += child_min; - natural += child_nat; + if (priv->is_homogeneous) + { + largest_min_size = MAX (largest_min_size, child_min); + largest_nat_size = MAX (largest_nat_size, child_nat); + } + else + { + minimum += child_min; + natural += child_nat; + } + } + + if (priv->is_homogeneous) + { + minimum = largest_min_size * n_children; + natural = largest_nat_size * n_children; } if (n_children > 1) @@ -623,6 +639,8 @@ } else { + size -= (nvis_children - 1) * priv->spacing; + /* Bring children up to size first */ if (isnormal (size) || size == 0) { diff -Nru mutter-3.36.1/clutter/clutter/clutter-click-action.c mutter-3.36.9/clutter/clutter/clutter-click-action.c --- mutter-3.36.1/clutter/clutter/clutter-click-action.c 2020-03-30 19:29:39.066890500 +0000 +++ mutter-3.36.9/clutter/clutter/clutter-click-action.c 2021-03-15 23:07:33.049507000 +0000 @@ -346,6 +346,12 @@ ClutterModifierType modifier_state; gboolean has_button = TRUE; + if (!clutter_actor_meta_get_enabled (CLUTTER_ACTOR_META (action))) + { + clutter_click_action_release (action); + return CLUTTER_EVENT_PROPAGATE; + } + actor = clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (action)); switch (clutter_event_type (event)) diff -Nru mutter-3.36.1/clutter/clutter/clutter-enums.h mutter-3.36.9/clutter/clutter/clutter-enums.h --- mutter-3.36.1/clutter/clutter/clutter-enums.h 2020-03-30 19:29:39.073890400 +0000 +++ mutter-3.36.9/clutter/clutter/clutter-enums.h 2021-03-15 23:07:33.054506800 +0000 @@ -934,6 +934,11 @@ CLUTTER_PAD_BUTTON_RELEASE, CLUTTER_PAD_STRIP, CLUTTER_PAD_RING, + CLUTTER_IM_COMMIT, + CLUTTER_IM_DELETE, + CLUTTER_IM_PREEDIT, + CLUTTER_DEVICE_ADDED, + CLUTTER_DEVICE_REMOVED, CLUTTER_EVENT_LAST /* helper */ } ClutterEventType; diff -Nru mutter-3.36.1/clutter/clutter/clutter-event.c mutter-3.36.9/clutter/clutter/clutter-event.c --- mutter-3.36.1/clutter/clutter/clutter-event.c 2020-03-30 19:29:39.073890400 +0000 +++ mutter-3.36.9/clutter/clutter/clutter-event.c 2021-03-15 23:07:33.054506800 +0000 @@ -415,6 +415,11 @@ case CLUTTER_PAD_BUTTON_RELEASE: case CLUTTER_PAD_STRIP: case CLUTTER_PAD_RING: + case CLUTTER_IM_COMMIT: + case CLUTTER_IM_DELETE: + case CLUTTER_IM_PREEDIT: + case CLUTTER_DEVICE_ADDED: + case CLUTTER_DEVICE_REMOVED: graphene_point_init (position, 0.f, 0.f); break; @@ -489,6 +494,11 @@ case CLUTTER_PAD_BUTTON_RELEASE: case CLUTTER_PAD_STRIP: case CLUTTER_PAD_RING: + case CLUTTER_IM_COMMIT: + case CLUTTER_IM_DELETE: + case CLUTTER_IM_PREEDIT: + case CLUTTER_DEVICE_ADDED: + case CLUTTER_DEVICE_REMOVED: break; case CLUTTER_ENTER: @@ -1107,6 +1117,9 @@ case CLUTTER_CLIENT_MESSAGE: case CLUTTER_DELETE: case CLUTTER_EVENT_LAST: + case CLUTTER_IM_COMMIT: + case CLUTTER_IM_DELETE: + case CLUTTER_IM_PREEDIT: break; case CLUTTER_ENTER: @@ -1161,6 +1174,11 @@ case CLUTTER_PAD_RING: event->pad_ring.device = device; break; + + case CLUTTER_DEVICE_ADDED: + case CLUTTER_DEVICE_REMOVED: + event->device.device = device; + break; } } @@ -1203,6 +1221,9 @@ case CLUTTER_DESTROY_NOTIFY: case CLUTTER_CLIENT_MESSAGE: case CLUTTER_DELETE: + case CLUTTER_IM_COMMIT: + case CLUTTER_IM_DELETE: + case CLUTTER_IM_PREEDIT: case CLUTTER_EVENT_LAST: break; @@ -1258,6 +1279,11 @@ case CLUTTER_PAD_RING: device = event->pad_ring.device; break; + + case CLUTTER_DEVICE_ADDED: + case CLUTTER_DEVICE_REMOVED: + device = event->device.device; + break; } return device; @@ -1411,6 +1437,16 @@ sizeof (gdouble) * n_axes); break; + case CLUTTER_IM_COMMIT: + case CLUTTER_IM_PREEDIT: + new_event->im.text = g_strdup (event->im.text); + break; + + case CLUTTER_DEVICE_ADDED: + case CLUTTER_DEVICE_REMOVED: + new_event->device.device = event->device.device; + break; + default: break; } @@ -1466,6 +1502,11 @@ g_free (event->touch.axes); break; + case CLUTTER_IM_COMMIT: + case CLUTTER_IM_PREEDIT: + g_free (event->im.text); + break; + default: break; } @@ -1541,7 +1582,9 @@ device = clutter_event_get_device (event); if (device != NULL) { - if (!clutter_input_device_get_enabled (device)) + if (event->type != CLUTTER_DEVICE_ADDED && + event->type != CLUTTER_DEVICE_REMOVED && + !clutter_input_device_get_enabled (device)) return; } @@ -1733,6 +1776,8 @@ case CLUTTER_EVENT_LAST: case CLUTTER_PROXIMITY_IN: case CLUTTER_PROXIMITY_OUT: + case CLUTTER_DEVICE_ADDED: + case CLUTTER_DEVICE_REMOVED: break; case CLUTTER_SCROLL: @@ -1761,6 +1806,9 @@ case CLUTTER_PAD_BUTTON_RELEASE: case CLUTTER_PAD_STRIP: case CLUTTER_PAD_RING: + case CLUTTER_IM_COMMIT: + case CLUTTER_IM_DELETE: + case CLUTTER_IM_PREEDIT: break; } diff -Nru mutter-3.36.1/clutter/clutter/clutter-event.h mutter-3.36.9/clutter/clutter/clutter-event.h --- mutter-3.36.1/clutter/clutter/clutter-event.h 2020-03-30 19:29:39.074890400 +0000 +++ mutter-3.36.9/clutter/clutter/clutter-event.h 2021-03-15 23:07:33.054506800 +0000 @@ -121,6 +121,8 @@ typedef struct _ClutterPadButtonEvent ClutterPadButtonEvent; typedef struct _ClutterPadStripEvent ClutterPadStripEvent; typedef struct _ClutterPadRingEvent ClutterPadRingEvent; +typedef struct _ClutterIMEvent ClutterIMEvent; +typedef struct _ClutterDeviceEvent ClutterDeviceEvent; /** * ClutterAnyEvent: @@ -544,6 +546,30 @@ guint32 mode; }; +struct _ClutterIMEvent +{ + ClutterEventType type; + guint32 time; + ClutterEventFlags flags; + ClutterStage *stage; + ClutterActor *source; + + char *text; + int32_t offset; + uint32_t len; +}; + +struct _ClutterDeviceEvent +{ + ClutterEventType type; + guint32 time; + ClutterEventFlags flags; + ClutterStage *stage; + ClutterActor *source; + + ClutterInputDevice *device; +}; + /** * ClutterEvent: * @@ -570,6 +596,8 @@ ClutterPadButtonEvent pad_button; ClutterPadStripEvent pad_strip; ClutterPadRingEvent pad_ring; + ClutterIMEvent im; + ClutterDeviceEvent device; }; /** diff -Nru mutter-3.36.1/clutter/clutter/clutter-input-focus.c mutter-3.36.9/clutter/clutter/clutter-input-focus.c --- mutter-3.36.1/clutter/clutter/clutter-input-focus.c 2020-03-30 19:29:39.079890300 +0000 +++ mutter-3.36.9/clutter/clutter/clutter-input-focus.c 2021-03-15 23:07:33.057506600 +0000 @@ -147,8 +147,8 @@ } gboolean -clutter_input_focus_filter_key_event (ClutterInputFocus *focus, - const ClutterKeyEvent *key) +clutter_input_focus_filter_event (ClutterInputFocus *focus, + const ClutterEvent *event) { ClutterInputFocusPrivate *priv; @@ -157,7 +157,30 @@ priv = clutter_input_focus_get_instance_private (focus); - return clutter_input_method_filter_key_event (priv->im, key); + if (event->type == CLUTTER_KEY_PRESS || + event->type == CLUTTER_KEY_RELEASE) + { + return clutter_input_method_filter_key_event (priv->im, &event->key); + } + else if (event->type == CLUTTER_IM_COMMIT) + { + clutter_input_focus_commit (focus, event->im.text); + return TRUE; + } + else if (event->type == CLUTTER_IM_DELETE) + { + clutter_input_focus_delete_surrounding (focus, event->im.offset, + event->im.len); + return TRUE; + } + else if (event->type == CLUTTER_IM_PREEDIT) + { + clutter_input_focus_set_preedit_text (focus, event->im.text, + event->im.offset); + return TRUE; + } + + return FALSE; } void diff -Nru mutter-3.36.1/clutter/clutter/clutter-input-focus.h mutter-3.36.9/clutter/clutter/clutter-input-focus.h --- mutter-3.36.1/clutter/clutter/clutter-input-focus.h 2020-03-30 19:29:39.079890300 +0000 +++ mutter-3.36.9/clutter/clutter/clutter-input-focus.h 2021-03-15 23:07:33.057506600 +0000 @@ -72,8 +72,8 @@ void clutter_input_focus_set_content_purpose (ClutterInputFocus *focus, ClutterInputContentPurpose purpose); CLUTTER_EXPORT -gboolean clutter_input_focus_filter_key_event (ClutterInputFocus *focus, - const ClutterKeyEvent *key); +gboolean clutter_input_focus_filter_event (ClutterInputFocus *focus, + const ClutterEvent *event); CLUTTER_EXPORT void clutter_input_focus_set_can_show_preedit (ClutterInputFocus *focus, gboolean can_show_preedit); diff -Nru mutter-3.36.1/clutter/clutter/clutter-input-method.c mutter-3.36.9/clutter/clutter/clutter-input-method.c --- mutter-3.36.1/clutter/clutter/clutter-input-method.c 2020-03-30 19:29:39.079890300 +0000 +++ mutter-3.36.9/clutter/clutter/clutter-input-method.c 2021-03-15 23:07:33.058506700 +0000 @@ -277,17 +277,45 @@ return priv->focus; } +static void +clutter_input_method_put_im_event (ClutterInputMethod *im, + ClutterEventType event_type, + const gchar *text, + int32_t offset, + uint32_t len) +{ + ClutterInputDevice *keyboard; + ClutterSeat *seat; + ClutterStage *stage; + ClutterEvent *event; + + seat = clutter_backend_get_default_seat (clutter_get_default_backend ()); + keyboard = clutter_seat_get_keyboard (seat); + stage = _clutter_input_device_get_stage (keyboard); + if (stage == NULL) + return; + + event = clutter_event_new (event_type); + event->im.text = g_strdup (text); + event->im.offset = offset; + event->im.len = len; + clutter_event_set_device (event, keyboard); + clutter_event_set_source_device (event, keyboard); + clutter_event_set_flags (event, CLUTTER_EVENT_FLAG_INPUT_METHOD); + + clutter_event_set_stage (event, stage); + + clutter_event_put (event); + clutter_event_free (event); +} + void clutter_input_method_commit (ClutterInputMethod *im, const gchar *text) { - ClutterInputMethodPrivate *priv; - g_return_if_fail (CLUTTER_IS_INPUT_METHOD (im)); - priv = clutter_input_method_get_instance_private (im); - if (priv->focus) - clutter_input_focus_commit (priv->focus, text); + clutter_input_method_put_im_event (im, CLUTTER_IM_COMMIT, text, 0, 0); } void @@ -295,13 +323,9 @@ int offset, guint len) { - ClutterInputMethodPrivate *priv; - g_return_if_fail (CLUTTER_IS_INPUT_METHOD (im)); - priv = clutter_input_method_get_instance_private (im); - if (priv->focus) - clutter_input_focus_delete_surrounding (priv->focus, offset, len); + clutter_input_method_put_im_event (im, CLUTTER_IM_DELETE, NULL, offset, len); } void @@ -329,13 +353,9 @@ const gchar *preedit, guint cursor) { - ClutterInputMethodPrivate *priv; - g_return_if_fail (CLUTTER_IS_INPUT_METHOD (im)); - priv = clutter_input_method_get_instance_private (im); - if (priv->focus) - clutter_input_focus_set_preedit_text (priv->focus, preedit, cursor); + clutter_input_method_put_im_event (im, CLUTTER_IM_PREEDIT, preedit, cursor, 0); } void diff -Nru mutter-3.36.1/clutter/clutter/clutter-main.c mutter-3.36.9/clutter/clutter/clutter-main.c --- mutter-3.36.1/clutter/clutter/clutter-main.c 2020-03-30 19:29:39.083890200 +0000 +++ mutter-3.36.9/clutter/clutter/clutter-main.c 2021-03-15 23:07:33.061506500 +0000 @@ -1749,6 +1749,9 @@ case CLUTTER_PAD_BUTTON_RELEASE: case CLUTTER_PAD_STRIP: case CLUTTER_PAD_RING: + case CLUTTER_IM_COMMIT: + case CLUTTER_IM_DELETE: + case CLUTTER_IM_PREEDIT: { ClutterActor *actor = NULL; @@ -2116,6 +2119,17 @@ case CLUTTER_CLIENT_MESSAGE: break; + case CLUTTER_DEVICE_ADDED: + case CLUTTER_DEVICE_REMOVED: + if (!_clutter_event_process_filters (event)) + { + ClutterSeat *seat; + + seat = clutter_backend_get_default_seat (context->backend); + clutter_seat_handle_device_event (seat, event); + } + break; + case CLUTTER_EVENT_LAST: break; } diff -Nru mutter-3.36.1/clutter/clutter/clutter-master-clock-default.c mutter-3.36.9/clutter/clutter/clutter-master-clock-default.c --- mutter-3.36.1/clutter/clutter/clutter-master-clock-default.c 2020-03-30 19:29:39.084890100 +0000 +++ mutter-3.36.9/clutter/clutter/clutter-master-clock-default.c 2021-03-15 23:07:33.062506400 +0000 @@ -190,6 +190,26 @@ } } +static int64_t +master_clock_get_next_presentation_time (ClutterMasterClockDefault *master_clock) +{ + ClutterStageManager *stage_manager = clutter_stage_manager_get_default (); + const GSList *stages, *l; + int64_t earliest = -1; + + stages = clutter_stage_manager_peek_stages (stage_manager); + + for (l = stages; l != NULL; l = l->next) + { + gint64 t = _clutter_stage_get_next_presentation_time (l->data); + + if (earliest == -1 || (t != -1 && t < earliest)) + earliest = t; + } + + return earliest; +} + static void master_clock_schedule_stage_updates (ClutterMasterClockDefault *master_clock) { @@ -199,7 +219,7 @@ stages = clutter_stage_manager_peek_stages (stage_manager); for (l = stages; l != NULL; l = l->next) - _clutter_stage_schedule_update (l->data); + clutter_stage_schedule_update (l->data); } static GSList * @@ -252,7 +272,7 @@ if (master_clock->timelines || _clutter_stage_has_queued_events (l->data) || _clutter_stage_needs_update (l->data)) - _clutter_stage_schedule_update (l->data); + clutter_stage_schedule_update (l->data); } } @@ -466,7 +486,11 @@ COGL_TRACE_BEGIN (ClutterMasterClockTick, "Master Clock (tick)"); /* Get the time to use for this frame */ - master_clock->cur_tick = g_source_get_time (source); + master_clock->cur_tick = master_clock_get_next_presentation_time (master_clock); + + /* On the first frame the backend might not have an answer */ + if (master_clock->cur_tick <= 0) + master_clock->cur_tick = g_source_get_time (source); #ifdef CLUTTER_ENABLE_DEBUG master_clock->remaining_budget = master_clock->frame_budget; diff -Nru mutter-3.36.1/clutter/clutter/clutter-mutter.h mutter-3.36.9/clutter/clutter/clutter-mutter.h --- mutter-3.36.1/clutter/clutter/clutter-mutter.h 2020-03-30 19:29:39.084890100 +0000 +++ mutter-3.36.9/clutter/clutter/clutter-mutter.h 2021-03-15 23:07:33.063506600 +0000 @@ -30,6 +30,7 @@ #include "clutter-input-device-private.h" #include "clutter-input-pointer-a11y-private.h" #include "clutter-macros.h" +#include "clutter-paint-context-private.h" #include "clutter-private.h" #include "clutter-stage-private.h" #include "clutter-stage-view.h" @@ -49,6 +50,23 @@ uint8_t *data); CLUTTER_EXPORT +void clutter_stage_paint_to_framebuffer (ClutterStage *stage, + CoglFramebuffer *framebuffer, + const cairo_rectangle_int_t *rect, + float scale, + ClutterPaintFlag paint_flags); + +CLUTTER_EXPORT +gboolean clutter_stage_paint_to_buffer (ClutterStage *stage, + const cairo_rectangle_int_t *rect, + float scale, + uint8_t *data, + int stride, + CoglPixelFormat format, + ClutterPaintFlag paint_flags, + GError **error); + +CLUTTER_EXPORT void clutter_stage_freeze_updates (ClutterStage *stage); CLUTTER_EXPORT diff -Nru mutter-3.36.1/clutter/clutter/clutter-paint-context.c mutter-3.36.9/clutter/clutter/clutter-paint-context.c --- mutter-3.36.1/clutter/clutter/clutter-paint-context.c 2020-03-30 19:29:39.085890000 +0000 +++ mutter-3.36.9/clutter/clutter/clutter-paint-context.c 2021-03-15 23:07:33.064506500 +0000 @@ -23,6 +23,8 @@ { grefcount ref_count; + ClutterPaintFlag paint_flags; + GList *framebuffers; ClutterStageView *view; @@ -36,7 +38,8 @@ ClutterPaintContext * clutter_paint_context_new_for_view (ClutterStageView *view, - const cairo_region_t *redraw_clip) + const cairo_region_t *redraw_clip, + ClutterPaintFlag paint_flags) { ClutterPaintContext *paint_context; CoglFramebuffer *framebuffer; @@ -45,6 +48,7 @@ g_ref_count_init (&paint_context->ref_count); paint_context->view = view; paint_context->redraw_clip = cairo_region_copy (redraw_clip); + paint_context->paint_flags = paint_flags; framebuffer = clutter_stage_view_get_framebuffer (view); clutter_paint_context_push_framebuffer (paint_context, framebuffer); @@ -62,6 +66,8 @@ paint_context = g_new0 (ClutterPaintContext, 1); g_ref_count_init (&paint_context->ref_count); + paint_context->paint_flags = (CLUTTER_PAINT_FLAG_NO_CURSORS | + CLUTTER_PAINT_FLAG_NO_PAINT_SIGNAL); clutter_paint_context_push_framebuffer (paint_context, framebuffer); @@ -170,3 +176,12 @@ return !paint_context->view; } + +/** + * clutter_paint_context_get_paint_flags: (skip) + */ +ClutterPaintFlag +clutter_paint_context_get_paint_flags (ClutterPaintContext *paint_context) +{ + return paint_context->paint_flags; +} diff -Nru mutter-3.36.1/clutter/clutter/clutter-paint-context-private.h mutter-3.36.9/clutter/clutter/clutter-paint-context-private.h --- mutter-3.36.1/clutter/clutter/clutter-paint-context-private.h 2020-03-30 19:29:39.085890000 +0000 +++ mutter-3.36.9/clutter/clutter/clutter-paint-context-private.h 2021-03-15 23:07:33.064506500 +0000 @@ -20,11 +20,22 @@ #include "clutter-paint-context.h" +typedef enum _ClutterPaintFlag +{ + CLUTTER_PAINT_FLAG_NONE = 0, + CLUTTER_PAINT_FLAG_NO_CURSORS = 1 << 0, + CLUTTER_PAINT_FLAG_NO_PAINT_SIGNAL = 1 << 1, +} ClutterPaintFlag; + ClutterPaintContext * clutter_paint_context_new_for_view (ClutterStageView *view, - const cairo_region_t *redraw_clip); + const cairo_region_t *redraw_clip, + ClutterPaintFlag paint_flags); gboolean clutter_paint_context_is_drawing_off_stage (ClutterPaintContext *paint_context); CoglFramebuffer * clutter_paint_context_get_base_framebuffer (ClutterPaintContext *paint_context); +CLUTTER_EXPORT +ClutterPaintFlag clutter_paint_context_get_paint_flags (ClutterPaintContext *paint_context); + #endif /* CLUTTER_PAINT_CONTEXT_PRIVATE_H */ diff -Nru mutter-3.36.1/clutter/clutter/clutter-seat.c mutter-3.36.9/clutter/clutter/clutter-seat.c --- mutter-3.36.1/clutter/clutter/clutter-seat.c 2020-03-30 19:29:39.091889900 +0000 +++ mutter-3.36.9/clutter/clutter/clutter-seat.c 2021-03-15 23:07:33.070506300 +0000 @@ -663,6 +663,46 @@ seat_class->compress_motion (seat, event, to_discard); } +gboolean +clutter_seat_handle_device_event (ClutterSeat *seat, + ClutterEvent *event) +{ + ClutterSeatClass *seat_class; + ClutterInputDevice *device; + + g_return_val_if_fail (CLUTTER_IS_SEAT (seat), FALSE); + g_return_val_if_fail (event, FALSE); + + g_assert (event->type == CLUTTER_DEVICE_ADDED || + event->type == CLUTTER_DEVICE_REMOVED); + + seat_class = CLUTTER_SEAT_GET_CLASS (seat); + + if (seat_class->handle_device_event) + { + if (!seat_class->handle_device_event (seat, event)) + return FALSE; + } + + device = clutter_event_get_source_device (event); + g_assert_true (CLUTTER_IS_INPUT_DEVICE (device)); + + switch (event->type) + { + case CLUTTER_DEVICE_ADDED: + g_signal_emit (seat, signals[DEVICE_ADDED], 0, device); + break; + case CLUTTER_DEVICE_REMOVED: + g_signal_emit (seat, signals[DEVICE_REMOVED], 0, device); + g_object_run_dispose (G_OBJECT (device)); + break; + default: + break; + } + + return TRUE; +} + void clutter_seat_warp_pointer (ClutterSeat *seat, int x, @@ -682,7 +722,6 @@ * requirements are fulfilled: * * - A touchscreen is available - * - No external keyboard is attached to the device * - A tablet mode switch, if present, is enabled * * Returns: %TRUE if the device is a tablet that doesn't have an external diff -Nru mutter-3.36.1/clutter/clutter/clutter-seat.h mutter-3.36.9/clutter/clutter/clutter-seat.h --- mutter-3.36.1/clutter/clutter/clutter-seat.h 2020-03-30 19:29:39.091889900 +0000 +++ mutter-3.36.9/clutter/clutter/clutter-seat.h 2021-03-15 23:07:33.070506300 +0000 @@ -106,6 +106,9 @@ ClutterEvent *event, const ClutterEvent *to_discard); + gboolean (* handle_device_event) (ClutterSeat *seat, + ClutterEvent *event); + void (* warp_pointer) (ClutterSeat *seat, int x, int y); @@ -180,6 +183,9 @@ ClutterEvent *event, const ClutterEvent *to_discard); +gboolean clutter_seat_handle_device_event (ClutterSeat *seat, + ClutterEvent *event); + CLUTTER_EXPORT void clutter_seat_warp_pointer (ClutterSeat *seat, int x, diff -Nru mutter-3.36.1/clutter/clutter/clutter-stage.c mutter-3.36.9/clutter/clutter/clutter-stage.c --- mutter-3.36.1/clutter/clutter/clutter-stage.c 2020-03-30 19:29:39.093890000 +0000 +++ mutter-3.36.9/clutter/clutter/clutter-stage.c 2021-03-15 23:07:33.080506000 +0000 @@ -145,6 +145,8 @@ int update_freeze_count; + gboolean needs_update; + guint redraw_pending : 1; guint is_cursor_visible : 1; guint throttle_motion_events : 1; @@ -934,7 +936,8 @@ ClutterPaintContext *paint_context; cairo_rectangle_int_t clip_rect; - paint_context = clutter_paint_context_new_for_view (view, redraw_clip); + paint_context = clutter_paint_context_new_for_view (view, redraw_clip, + CLUTTER_PAINT_FLAG_NONE); cairo_region_get_extents (redraw_clip, &clip_rect); setup_view_for_pick_or_paint (stage, view, &clip_rect); @@ -1179,7 +1182,7 @@ { ClutterMasterClock *master_clock = _clutter_master_clock_get_default (); _clutter_master_clock_start_running (master_clock); - _clutter_stage_schedule_update (stage); + clutter_stage_schedule_update (stage); } } @@ -1311,7 +1314,9 @@ priv = stage->priv; - return priv->redraw_pending || g_hash_table_size (priv->pending_relayouts) > 0; + return (priv->redraw_pending || + priv->needs_update || + g_hash_table_size (priv->pending_relayouts) > 0); } void @@ -1320,14 +1325,8 @@ { ClutterStagePrivate *priv = stage->priv; - if (g_hash_table_contains (priv->pending_relayouts, stage)) - return; - if (g_hash_table_size (priv->pending_relayouts) == 0) - _clutter_stage_schedule_update (stage); - - if (actor == (ClutterActor *) stage) - g_hash_table_remove_all (priv->pending_relayouts); + clutter_stage_schedule_update (stage); g_hash_table_add (priv->pending_relayouts, g_object_ref (actor)); priv->pending_relayouts_version++; @@ -1509,6 +1508,8 @@ priv->stage_was_relayout = FALSE; + priv->needs_update = FALSE; + /* if the stage is being destroyed, or if the destruction already * happened and we don't have an StageWindow any more, then we * should bail out @@ -3408,7 +3409,7 @@ priv = stage->priv; if (!_clutter_stage_needs_update (stage)) - _clutter_stage_schedule_update (stage); + clutter_stage_schedule_update (stage); priv->redraw_pending = TRUE; @@ -3686,13 +3687,13 @@ } /** - * _clutter_stage_schedule_update: - * @window: a #ClutterStage actor + * clutter_stage_schedule_update: + * @stage: a #ClutterStage actor * * Schedules a redraw of the #ClutterStage at the next optimal timestamp. */ void -_clutter_stage_schedule_update (ClutterStage *stage) +clutter_stage_schedule_update (ClutterStage *stage) { ClutterStageWindow *stage_window; @@ -3703,6 +3704,8 @@ if (stage_window == NULL) return; + stage->priv->needs_update = TRUE; + return _clutter_stage_window_schedule_update (stage_window, stage->priv->sync_delay); } @@ -3712,7 +3715,7 @@ * @stage: a #ClutterStage actor * * Returns the earliest time in which the stage is ready to update. The update - * time is set when _clutter_stage_schedule_update() is called. This can then + * time is set when clutter_stage_schedule_update() is called. This can then * be used by e.g. the #ClutterMasterClock to know when the stage needs to be * redrawn. * @@ -3751,6 +3754,21 @@ _clutter_stage_window_clear_update_time (stage_window); } +int64_t +_clutter_stage_get_next_presentation_time (ClutterStage *stage) +{ + ClutterStageWindow *stage_window; + + if (CLUTTER_ACTOR_IN_DESTRUCTION (stage)) + return 0; + + stage_window = _clutter_stage_get_window (stage); + if (stage_window == NULL) + return 0; + + return _clutter_stage_window_get_next_presentation_time (stage_window); +} + ClutterPaintVolume * _clutter_stage_paint_volume_stack_allocate (ClutterStage *stage) { @@ -3822,7 +3840,7 @@ CLUTTER_NOTE (PAINT, "First redraw request"); - _clutter_stage_schedule_update (stage); + clutter_stage_schedule_update (stage); priv->redraw_pending = TRUE; master_clock = _clutter_master_clock_get_default (); @@ -4220,7 +4238,7 @@ ClutterStageState set_flags) { ClutterStageState new_state; - ClutterEvent event; + ClutterEvent *event; new_state = stage->priv->current_state; new_state |= set_flags; @@ -4229,16 +4247,16 @@ if (new_state == stage->priv->current_state) return FALSE; - memset (&event, 0, sizeof (event)); - event.type = CLUTTER_STAGE_STATE; - clutter_event_set_stage (&event, stage); + event = clutter_event_new (CLUTTER_STAGE_STATE); + clutter_event_set_stage (event, stage); - event.stage_state.new_state = new_state; - event.stage_state.changed_mask = new_state ^ stage->priv->current_state; + event->stage_state.new_state = new_state; + event->stage_state.changed_mask = new_state ^ stage->priv->current_state; stage->priv->current_state = new_state; - clutter_stage_event (stage, &event); + clutter_stage_event (stage, event); + clutter_event_free (event); return TRUE; } @@ -4463,58 +4481,119 @@ return TRUE; } -static void -capture_view_into (ClutterStage *stage, - gboolean paint, - ClutterStageView *view, - cairo_rectangle_int_t *rect, - uint8_t *data, - int stride) +/** + * clutter_stage_paint_to_framebuffer: (skip) + */ +void +clutter_stage_paint_to_framebuffer (ClutterStage *stage, + CoglFramebuffer *framebuffer, + const cairo_rectangle_int_t *rect, + float scale, + ClutterPaintFlag paint_flags) { + ClutterStagePrivate *priv = stage->priv; + ClutterPaintContext *paint_context; + cairo_region_t *redraw_clip; + + redraw_clip = cairo_region_create_rectangle (rect); + paint_context = clutter_paint_context_new_for_framebuffer (framebuffer); + cairo_region_destroy (redraw_clip); + + cogl_framebuffer_push_matrix (framebuffer); + cogl_framebuffer_set_projection_matrix (framebuffer, &priv->projection); + cogl_framebuffer_set_viewport (framebuffer, + -(rect->x * scale), + -(rect->y * scale), + priv->viewport[2] * scale, + priv->viewport[3] * scale); + clutter_actor_paint (CLUTTER_ACTOR (stage), paint_context); + cogl_framebuffer_pop_matrix (framebuffer); + + clutter_paint_context_destroy (paint_context); +} + +/** + * clutter_stage_paint_to_buffer: (skip) + */ +gboolean +clutter_stage_paint_to_buffer (ClutterStage *stage, + const cairo_rectangle_int_t *rect, + float scale, + uint8_t *data, + int stride, + CoglPixelFormat format, + ClutterPaintFlag paint_flags, + GError **error) +{ + ClutterBackend *clutter_backend = clutter_get_default_backend (); + CoglContext *cogl_context = + clutter_backend_get_cogl_context (clutter_backend); + int texture_width, texture_height; + CoglTexture2D *texture; + CoglOffscreen *offscreen; CoglFramebuffer *framebuffer; - ClutterBackend *backend; - CoglContext *context; CoglBitmap *bitmap; - cairo_rectangle_int_t view_layout; - float view_scale; - float texture_width; - float texture_height; - g_return_if_fail (CLUTTER_IS_STAGE (stage)); + texture_width = (int) roundf (rect->width * scale); + texture_height = (int) roundf (rect->height * scale); + texture = cogl_texture_2d_new_with_size (cogl_context, + texture_width, + texture_height); + if (!texture) + { + g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, + "Failed to create %dx%d texture", + texture_width, texture_height); + return FALSE; + } - framebuffer = clutter_stage_view_get_framebuffer (view); + offscreen = cogl_offscreen_new_with_texture (COGL_TEXTURE (texture)); + framebuffer = COGL_FRAMEBUFFER (offscreen); - if (paint) - { - cairo_region_t *region; + cogl_object_unref (texture); - _clutter_stage_maybe_setup_viewport (stage, view); - region = cairo_region_create_rectangle (rect); - clutter_stage_do_paint_view (stage, view, region); - cairo_region_destroy (region); - } + if (!cogl_framebuffer_allocate (framebuffer, error)) + return FALSE; - view_scale = clutter_stage_view_get_scale (view); - texture_width = roundf (rect->width * view_scale); - texture_height = roundf (rect->height * view_scale); + clutter_stage_paint_to_framebuffer (stage, framebuffer, + rect, scale, paint_flags); - backend = clutter_get_default_backend (); - context = clutter_backend_get_cogl_context (backend); - bitmap = cogl_bitmap_new_for_data (context, + bitmap = cogl_bitmap_new_for_data (cogl_context, texture_width, texture_height, - CLUTTER_CAIRO_FORMAT_ARGB32, + format, stride, data); - clutter_stage_view_get_layout (view, &view_layout); - cogl_framebuffer_read_pixels_into_bitmap (framebuffer, - roundf ((rect->x - view_layout.x) * view_scale), - roundf ((rect->y - view_layout.y) * view_scale), + 0, 0, COGL_READ_PIXELS_COLOR_BUFFER, bitmap); cogl_object_unref (bitmap); + cogl_object_unref (framebuffer); + + return TRUE; +} + +static void +capture_view_into (ClutterStage *stage, + gboolean paint, + ClutterStageView *view, + cairo_rectangle_int_t *rect, + uint8_t *data, + int stride) +{ + g_autoptr (GError) error = NULL; + float view_scale; + + g_return_if_fail (CLUTTER_IS_STAGE (stage)); + + view_scale = clutter_stage_view_get_scale (view); + if (!clutter_stage_paint_to_buffer (stage, rect, view_scale, data, stride, + CLUTTER_CAIRO_FORMAT_ARGB32, + CLUTTER_PAINT_FLAG_NO_CURSORS, + &error)) + g_warning ("Failed to capture stage: %s", error->message); } void diff -Nru mutter-3.36.1/clutter/clutter/clutter-stage.h mutter-3.36.9/clutter/clutter/clutter-stage.h --- mutter-3.36.1/clutter/clutter/clutter-stage.h 2020-03-30 19:29:39.094889900 +0000 +++ mutter-3.36.9/clutter/clutter/clutter-stage.h 2021-03-15 23:07:33.080506000 +0000 @@ -223,6 +223,9 @@ #endif CLUTTER_EXPORT +void clutter_stage_schedule_update (ClutterStage *stage); + +CLUTTER_EXPORT gboolean clutter_stage_get_capture_final_size (ClutterStage *stage, cairo_rectangle_int_t *rect, int *width, diff -Nru mutter-3.36.1/clutter/clutter/clutter-stage-private.h mutter-3.36.9/clutter/clutter/clutter-stage-private.h --- mutter-3.36.1/clutter/clutter/clutter-stage-private.h 2020-03-30 19:29:39.092889800 +0000 +++ mutter-3.36.9/clutter/clutter/clutter-stage-private.h 2021-03-15 23:07:33.074506300 +0000 @@ -74,10 +74,10 @@ gboolean _clutter_stage_has_queued_events (ClutterStage *stage); void _clutter_stage_process_queued_events (ClutterStage *stage); void _clutter_stage_update_input_devices (ClutterStage *stage); -void _clutter_stage_schedule_update (ClutterStage *stage); gint64 _clutter_stage_get_update_time (ClutterStage *stage); void _clutter_stage_clear_update_time (ClutterStage *stage); gboolean _clutter_stage_has_full_redraw_queued (ClutterStage *stage); +int64_t _clutter_stage_get_next_presentation_time (ClutterStage *stage); void clutter_stage_log_pick (ClutterStage *stage, const graphene_point_t *vertices, diff -Nru mutter-3.36.1/clutter/clutter/clutter-stage-window.c mutter-3.36.9/clutter/clutter/clutter-stage-window.c --- mutter-3.36.1/clutter/clutter/clutter-stage-window.c 2020-03-30 19:29:39.092889800 +0000 +++ mutter-3.36.9/clutter/clutter/clutter-stage-window.c 2021-03-15 23:07:33.076506100 +0000 @@ -178,6 +178,22 @@ iface->clear_update_time (window); } +int64_t +_clutter_stage_window_get_next_presentation_time (ClutterStageWindow *window) +{ + ClutterStageWindowInterface *iface; + + g_return_val_if_fail (CLUTTER_IS_STAGE_WINDOW (window), 0); + + iface = CLUTTER_STAGE_WINDOW_GET_IFACE (window); + + /* If not implemented then just revert to the old behaviour... */ + if (iface->get_next_presentation_time == NULL) + return _clutter_stage_window_get_update_time (window); + + return iface->get_next_presentation_time (window); +} + void _clutter_stage_window_set_accept_focus (ClutterStageWindow *window, gboolean accept_focus) diff -Nru mutter-3.36.1/clutter/clutter/clutter-stage-window.h mutter-3.36.9/clutter/clutter/clutter-stage-window.h --- mutter-3.36.1/clutter/clutter/clutter-stage-window.h 2020-03-30 19:29:39.093890000 +0000 +++ mutter-3.36.9/clutter/clutter/clutter-stage-window.h 2021-03-15 23:07:33.076506100 +0000 @@ -61,6 +61,8 @@ GList *(* get_views) (ClutterStageWindow *stage_window); int64_t (* get_frame_counter) (ClutterStageWindow *stage_window); void (* finish_frame) (ClutterStageWindow *stage_window); + + int64_t (* get_next_presentation_time) (ClutterStageWindow *stage_window); }; ClutterActor * _clutter_stage_window_get_wrapper (ClutterStageWindow *window); @@ -101,6 +103,8 @@ int64_t _clutter_stage_window_get_frame_counter (ClutterStageWindow *window); +int64_t _clutter_stage_window_get_next_presentation_time (ClutterStageWindow *window); + G_END_DECLS #endif /* __CLUTTER_STAGE_WINDOW_H__ */ diff -Nru mutter-3.36.1/clutter/clutter/clutter-text.c mutter-3.36.9/clutter/clutter/clutter-text.c --- mutter-3.36.1/clutter/clutter/clutter-text.c 2020-03-30 19:29:39.095889800 +0000 +++ mutter-3.36.9/clutter/clutter/clutter-text.c 2021-03-15 23:07:33.083505900 +0000 @@ -2418,7 +2418,7 @@ if (!(event->flags & CLUTTER_EVENT_FLAG_INPUT_METHOD) && clutter_input_focus_is_focused (priv->input_focus) && - clutter_input_focus_filter_key_event (priv->input_focus, event)) + clutter_input_focus_filter_event (priv->input_focus, (ClutterEvent *) event)) return CLUTTER_EVENT_STOP; /* we allow passing synthetic events that only contain @@ -2487,7 +2487,7 @@ ClutterTextPrivate *priv = self->priv; if (clutter_input_focus_is_focused (priv->input_focus) && - clutter_input_focus_filter_key_event (priv->input_focus, event)) + clutter_input_focus_filter_event (priv->input_focus, (ClutterEvent *) event)) return CLUTTER_EVENT_STOP; return CLUTTER_EVENT_PROPAGATE; @@ -3064,6 +3064,24 @@ return clutter_text_should_draw_cursor ((ClutterText *) self); } +static gboolean +clutter_text_event (ClutterActor *self, + ClutterEvent *event) +{ + ClutterText *text = CLUTTER_TEXT (self); + ClutterTextPrivate *priv = text->priv; + + if (clutter_input_focus_is_focused (priv->input_focus) && + (event->type == CLUTTER_IM_COMMIT || + event->type == CLUTTER_IM_DELETE || + event->type == CLUTTER_IM_PREEDIT)) + { + return clutter_input_focus_filter_event (priv->input_focus, event); + } + + return CLUTTER_EVENT_PROPAGATE; +} + static void clutter_text_im_focus (ClutterText *text) { @@ -3812,6 +3830,7 @@ actor_class->key_focus_in = clutter_text_key_focus_in; actor_class->key_focus_out = clutter_text_key_focus_out; actor_class->has_overlaps = clutter_text_has_overlaps; + actor_class->event = clutter_text_event; /** * ClutterText:buffer: @@ -5956,6 +5975,55 @@ return self->priv->wrap_mode; } +static gboolean +attr_list_equal (PangoAttrList *old_attrs, PangoAttrList *new_attrs) +{ + PangoAttrIterator *i, *j; + gboolean equal = TRUE; + + if (old_attrs == new_attrs) + return TRUE; + + if (old_attrs == NULL || new_attrs == NULL) + return FALSE; + + i = pango_attr_list_get_iterator (old_attrs); + j = pango_attr_list_get_iterator (new_attrs); + + do + { + GSList *old_attributes, *new_attributes, *a, *b; + + old_attributes = pango_attr_iterator_get_attrs (i); + new_attributes = pango_attr_iterator_get_attrs (j); + + for (a = old_attributes, b = new_attributes; + a != NULL && b != NULL && equal; + a = a->next, b = b->next) + { + if (!pango_attribute_equal (a->data, b->data)) + equal = FALSE; + } + + if (a != NULL || b != NULL) + equal = FALSE; + + g_slist_free_full (old_attributes, + (GDestroyNotify) pango_attribute_destroy); + g_slist_free_full (new_attributes, + (GDestroyNotify) pango_attribute_destroy); + } + while (equal && pango_attr_iterator_next (i) && pango_attr_iterator_next (j)); + + if (pango_attr_iterator_next (i) || pango_attr_iterator_next (j)) + equal = FALSE; + + pango_attr_iterator_destroy (i); + pango_attr_iterator_destroy (j); + + return equal; +} + /** * clutter_text_set_attributes: * @self: a #ClutterText @@ -5979,10 +6047,7 @@ priv = self->priv; - /* While we should probably test for equality, Pango doesn't - * provide us an easy method to check for AttrList equality. - */ - if (priv->attrs == attrs) + if (attr_list_equal (priv->attrs, attrs)) return; if (attrs) diff -Nru mutter-3.36.1/clutter/clutter/cogl/clutter-stage-cogl.c mutter-3.36.9/clutter/clutter/cogl/clutter-stage-cogl.c --- mutter-3.36.1/clutter/clutter/cogl/clutter-stage-cogl.c 2020-03-30 19:29:39.098889800 +0000 +++ mutter-3.36.9/clutter/clutter/cogl/clutter-stage-cogl.c 2021-03-15 23:07:33.086506000 +0000 @@ -235,7 +235,12 @@ stage_cogl->update_time = next_presentation_time - max_render_time_allowed; if (stage_cogl->update_time == stage_cogl->last_update_time) - stage_cogl->update_time = stage_cogl->last_update_time + refresh_interval; + { + stage_cogl->update_time += refresh_interval; + next_presentation_time += refresh_interval; + } + + stage_cogl->next_presentation_time = next_presentation_time; } static gint64 @@ -256,6 +261,29 @@ stage_cogl->last_update_time = stage_cogl->update_time; stage_cogl->update_time = -1; + stage_cogl->next_presentation_time = -1; +} + +static int64_t +clutter_stage_cogl_get_next_presentation_time (ClutterStageWindow *stage_window) +{ + ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window); + int64_t now = g_get_monotonic_time (); + + if (stage_cogl->next_presentation_time > 0 && + stage_cogl->next_presentation_time <= now) + { + CLUTTER_NOTE (BACKEND, + "Missed some frames. Something blocked for over " + "%" G_GINT64_FORMAT "ms.", + (now - stage_cogl->next_presentation_time) / 1000); + + stage_cogl->update_time = -1; + clutter_stage_cogl_schedule_update (stage_window, + stage_cogl->last_sync_delay); + } + + return stage_cogl->next_presentation_time; } static ClutterActor * @@ -375,15 +403,11 @@ swap_framebuffer (ClutterStageWindow *stage_window, ClutterStageView *view, cairo_region_t *swap_region, - gboolean swap_with_damage, - cairo_region_t *queued_redraw_clip) + gboolean swap_with_damage) { CoglFramebuffer *framebuffer = clutter_stage_view_get_onscreen (view); int *damage, n_rects, i; - if (G_UNLIKELY ((clutter_paint_debug_flags & CLUTTER_DEBUG_PAINT_DAMAGE_REGION))) - paint_damage_region (stage_window, view, swap_region, queued_redraw_clip); - n_rects = cairo_region_num_rectangles (swap_region); damage = g_newa (int, n_rects * 4); for (i = 0; i < n_rects; i++) @@ -620,7 +644,7 @@ gboolean swap_with_damage; ClutterActor *wrapper; cairo_region_t *redraw_clip; - cairo_region_t *queued_redraw_clip; + cairo_region_t *queued_redraw_clip = NULL; cairo_region_t *fb_clip_region; cairo_region_t *swap_region; cairo_rectangle_int_t redraw_rect; @@ -644,6 +668,8 @@ has_buffer_age = cogl_is_onscreen (fb) && is_buffer_age_enabled (); redraw_clip = clutter_stage_view_take_redraw_clip (view); + if (G_UNLIKELY (clutter_paint_debug_flags & CLUTTER_DEBUG_PAINT_DAMAGE_REGION)) + queued_redraw_clip = cairo_region_copy (redraw_clip); /* NB: a NULL redraw clip == full stage redraw */ if (!redraw_clip) @@ -711,8 +737,6 @@ redraw_clip = cairo_region_create_rectangle (&view_rect); } - queued_redraw_clip = cairo_region_copy (redraw_clip); - if (may_use_clipped_redraw && G_LIKELY (!(clutter_paint_debug_flags & CLUTTER_DEBUG_DISABLE_CLIPPED_REDRAWS))) use_clipped_redraw = TRUE; @@ -911,7 +935,7 @@ } else { - swap_region = cairo_region_copy (fb_clip_region); + swap_region = cairo_region_reference (fb_clip_region); do_swap_buffer = TRUE; } } @@ -922,7 +946,6 @@ } g_clear_pointer (&redraw_clip, cairo_region_destroy); - g_clear_pointer (&queued_redraw_clip, cairo_region_destroy); g_clear_pointer (&fb_clip_region, cairo_region_destroy); if (do_swap_buffer) @@ -943,11 +966,17 @@ swap_region = transformed_swap_region; } + if (queued_redraw_clip) + { + paint_damage_region (stage_window, view, + swap_region, queued_redraw_clip); + cairo_region_destroy (queued_redraw_clip); + } + res = swap_framebuffer (stage_window, view, swap_region, - swap_with_damage, - queued_redraw_clip); + swap_with_damage); cairo_region_destroy (swap_region); @@ -955,6 +984,7 @@ } else { + g_clear_pointer (&queued_redraw_clip, cairo_region_destroy); return FALSE; } } @@ -1008,6 +1038,7 @@ iface->schedule_update = clutter_stage_cogl_schedule_update; iface->get_update_time = clutter_stage_cogl_get_update_time; iface->clear_update_time = clutter_stage_cogl_clear_update_time; + iface->get_next_presentation_time = clutter_stage_cogl_get_next_presentation_time; iface->redraw = clutter_stage_cogl_redraw; } @@ -1053,6 +1084,7 @@ stage->refresh_rate = 0.0; stage->update_time = -1; + stage->next_presentation_time = -1; } static void diff -Nru mutter-3.36.1/clutter/clutter/cogl/clutter-stage-cogl.h mutter-3.36.9/clutter/clutter/cogl/clutter-stage-cogl.h --- mutter-3.36.1/clutter/clutter/cogl/clutter-stage-cogl.h 2020-03-30 19:29:39.098889800 +0000 +++ mutter-3.36.9/clutter/clutter/cogl/clutter-stage-cogl.h 2021-03-15 23:07:33.087505800 +0000 @@ -48,6 +48,7 @@ gint64 last_presentation_time; gint64 update_time; int64_t last_update_time; + int64_t next_presentation_time; /* We only enable clipped redraws after 2 frames, since we've seen * a lot of drivers can struggle to get going and may output some diff -Nru mutter-3.36.1/cogl/cogl/cogl-onscreen.c mutter-3.36.9/cogl/cogl/cogl-onscreen.c --- mutter-3.36.1/cogl/cogl/cogl-onscreen.c 2020-03-30 19:29:39.124889100 +0000 +++ mutter-3.36.9/cogl/cogl/cogl-onscreen.c 2021-03-15 23:07:33.118505000 +0000 @@ -93,10 +93,12 @@ CoglOnscreen * _cogl_onscreen_new (void) { - CoglOnscreen *onscreen = g_new0 (CoglOnscreen, 1); + g_autofree CoglOnscreen *onscreen_ptr = g_new0 (CoglOnscreen, 1); + CoglOnscreen *onscreen; _COGL_GET_CONTEXT (ctx, NULL); + onscreen = g_steal_pointer (&onscreen_ptr); _cogl_framebuffer_init (COGL_FRAMEBUFFER (onscreen), ctx, COGL_FRAMEBUFFER_TYPE_ONSCREEN, diff -Nru mutter-3.36.1/cogl/cogl/cogl-pipeline-cache.c mutter-3.36.9/cogl/cogl/cogl-pipeline-cache.c --- mutter-3.36.1/cogl/cogl/cogl-pipeline-cache.c 2020-03-30 19:29:39.124889100 +0000 +++ mutter-3.36.9/cogl/cogl/cogl-pipeline-cache.c 2021-03-15 23:07:33.119505000 +0000 @@ -50,7 +50,7 @@ CoglPipelineCache * _cogl_pipeline_cache_new (void) { - CoglPipelineCache *cache = g_new (CoglPipelineCache, 1); + g_autofree CoglPipelineCache *cache = g_new (CoglPipelineCache, 1); unsigned long vertex_state; unsigned long layer_vertex_state; unsigned int fragment_state; @@ -80,7 +80,7 @@ layer_vertex_state | layer_fragment_state, "programs"); - return cache; + return g_steal_pointer (&cache); } void diff -Nru mutter-3.36.1/cogl/cogl/cogl-pipeline-layer-state.c mutter-3.36.9/cogl/cogl/cogl-pipeline-layer-state.c --- mutter-3.36.1/cogl/cogl/cogl-pipeline-layer-state.c 2020-03-30 19:29:39.125889000 +0000 +++ mutter-3.36.9/cogl/cogl/cogl-pipeline-layer-state.c 2021-03-15 23:07:33.119505000 +0000 @@ -1361,6 +1361,17 @@ sampler_state); } +void +cogl_pipeline_set_layer_max_mipmap_level (CoglPipeline *pipeline, + int layer, + int max_level) +{ + CoglTexture *texture = cogl_pipeline_get_layer_texture (pipeline, layer); + + if (texture != NULL) + cogl_texture_set_max_level (texture, max_level); +} + const CoglSamplerCacheEntry * _cogl_pipeline_layer_get_sampler_state (CoglPipelineLayer *layer) { diff -Nru mutter-3.36.1/cogl/cogl/cogl-pipeline-layer-state.h mutter-3.36.9/cogl/cogl/cogl-pipeline-layer-state.h --- mutter-3.36.1/cogl/cogl/cogl-pipeline-layer-state.h 2020-03-30 19:29:39.126889200 +0000 +++ mutter-3.36.9/cogl/cogl/cogl-pipeline-layer-state.h 2021-03-15 23:07:33.120504900 +0000 @@ -568,6 +568,11 @@ int layer, CoglSnippet *snippet); +COGL_EXPORT void +cogl_pipeline_set_layer_max_mipmap_level (CoglPipeline *pipeline, + int layer, + int max_level); + G_END_DECLS #endif /* __COGL_PIPELINE_LAYER_STATE_H__ */ diff -Nru mutter-3.36.1/cogl/cogl/cogl-texture-2d.c mutter-3.36.9/cogl/cogl/cogl-texture-2d.c --- mutter-3.36.1/cogl/cogl/cogl-texture-2d.c 2020-03-30 19:29:39.136889000 +0000 +++ mutter-3.36.9/cogl/cogl/cogl-texture-2d.c 2021-03-15 23:07:33.130504600 +0000 @@ -121,6 +121,9 @@ { CoglTextureLoader *loader; + g_return_val_if_fail (width >= 1, NULL); + g_return_val_if_fail (height >= 1, NULL); + loader = _cogl_texture_create_loader (); loader->src_type = COGL_TEXTURE_SOURCE_TYPE_SIZED; loader->src.sized.width = width; @@ -399,6 +402,11 @@ { CoglContext *ctx = tex->context; + /* Since we are about to ask the GPU to generate mipmaps of tex, we + * better make sure tex is up-to-date. + */ + _cogl_texture_flush_journal_rendering (tex); + ctx->driver_vtable->texture_2d_generate_mipmap (tex_2d); tex_2d->mipmaps_dirty = FALSE; diff -Nru mutter-3.36.1/cogl/cogl/cogl-texture.c mutter-3.36.9/cogl/cogl/cogl-texture.c --- mutter-3.36.1/cogl/cogl/cogl-texture.c 2020-03-30 19:29:39.136889000 +0000 +++ mutter-3.36.9/cogl/cogl/cogl-texture.c 2021-03-15 23:07:33.130504600 +0000 @@ -115,7 +115,8 @@ const CoglTextureVtable *vtable) { texture->context = context; - texture->max_level = 0; + texture->max_level_set = 0; + texture->max_level_requested = 1000; /* OpenGL default GL_TEXTURE_MAX_LEVEL */ texture->width = width; texture->height = height; texture->allocated = FALSE; @@ -229,8 +230,16 @@ int width = cogl_texture_get_width (texture); int height = cogl_texture_get_height (texture); int max_dimension = MAX (width, height); + int n_levels = _cogl_util_fls (max_dimension); - return _cogl_util_fls (max_dimension); + return MIN (n_levels, texture->max_level_requested + 1); +} + +void +cogl_texture_set_max_level (CoglTexture *texture, + int max_level) +{ + texture->max_level_requested = max_level; } void diff -Nru mutter-3.36.1/cogl/cogl/cogl-texture-private.h mutter-3.36.9/cogl/cogl/cogl-texture-private.h --- mutter-3.36.1/cogl/cogl/cogl-texture-private.h 2020-03-30 19:29:39.136889000 +0000 +++ mutter-3.36.9/cogl/cogl/cogl-texture-private.h 2021-03-15 23:07:33.130504600 +0000 @@ -204,7 +204,8 @@ CoglContext *context; CoglTextureLoader *loader; GList *framebuffers; - int max_level; + int max_level_set; + int max_level_requested; int width; int height; gboolean allocated; @@ -378,6 +379,10 @@ _cogl_texture_get_n_levels (CoglTexture *texture); void +cogl_texture_set_max_level (CoglTexture *texture, + int max_level); + +void _cogl_texture_get_level_size (CoglTexture *texture, int level, int *width, diff -Nru mutter-3.36.1/cogl/cogl/driver/gl/cogl-framebuffer-gl.c mutter-3.36.9/cogl/cogl/driver/gl/cogl-framebuffer-gl.c --- mutter-3.36.1/cogl/cogl/driver/gl/cogl-framebuffer-gl.c 2020-03-30 19:29:39.142888800 +0000 +++ mutter-3.36.9/cogl/cogl/driver/gl/cogl-framebuffer-gl.c 2021-03-15 23:07:33.135504500 +0000 @@ -132,8 +132,8 @@ { float gl_viewport_y; - g_assert (framebuffer->viewport_width >=0 && - framebuffer->viewport_height >=0); + g_return_if_fail (framebuffer->viewport_width >= 0); + g_return_if_fail (framebuffer->viewport_height >= 0); /* Convert the Cogl viewport y offset to an OpenGL viewport y offset * NB: OpenGL defines its window and viewport origins to be bottom diff -Nru mutter-3.36.1/cogl/cogl/driver/gl/cogl-texture-2d-gl.c mutter-3.36.9/cogl/cogl/driver/gl/cogl-texture-2d-gl.c --- mutter-3.36.1/cogl/cogl/driver/gl/cogl-texture-2d-gl.c 2020-03-30 19:29:39.145888600 +0000 +++ mutter-3.36.9/cogl/cogl/driver/gl/cogl-texture-2d-gl.c 2021-03-15 23:07:33.138504500 +0000 @@ -567,6 +567,9 @@ &gl_format, &gl_type); + if (tex->max_level_set < level) + cogl_texture_gl_set_max_level (tex, level); + status = ctx->texture_driver->upload_subregion_to_gl (ctx, tex, src_x, src_y, @@ -580,8 +583,6 @@ cogl_object_unref (upload_bmp); - _cogl_texture_gl_maybe_update_max_level (tex, level); - return status; } diff -Nru mutter-3.36.1/cogl/cogl/driver/gl/cogl-texture-gl.c mutter-3.36.9/cogl/cogl/driver/gl/cogl-texture-gl.c --- mutter-3.36.1/cogl/cogl/driver/gl/cogl-texture-gl.c 2020-03-30 19:29:39.145888600 +0000 +++ mutter-3.36.9/cogl/cogl/driver/gl/cogl-texture-gl.c 2021-03-15 23:07:33.138504500 +0000 @@ -97,32 +97,36 @@ min_filter, mag_filter); } +/* GL and GLES3 have this by default, but GLES2 does not except via extension. + * So really it's probably always available. Even if we used it and it wasn't + * available in some driver then there are no adverse consequences to the + * command simply being ignored... + */ +#ifndef GL_TEXTURE_MAX_LEVEL +#define GL_TEXTURE_MAX_LEVEL 0x813D +#endif + void -_cogl_texture_gl_maybe_update_max_level (CoglTexture *texture, - int max_level) +cogl_texture_gl_set_max_level (CoglTexture *texture, + int max_level) { - /* This isn't supported on GLES */ -#ifdef HAVE_COGL_GL CoglContext *ctx = texture->context; - if (_cogl_has_private_feature (ctx, COGL_PRIVATE_FEATURE_TEXTURE_MAX_LEVEL) && - texture->max_level < max_level) + if (_cogl_has_private_feature (ctx, COGL_PRIVATE_FEATURE_TEXTURE_MAX_LEVEL)) { - CoglContext *ctx = texture->context; GLuint gl_handle; GLenum gl_target; cogl_texture_get_gl_texture (texture, &gl_handle, &gl_target); - texture->max_level = max_level; + texture->max_level_set = max_level; _cogl_bind_gl_texture_transient (gl_target, gl_handle); GE( ctx, glTexParameteri (gl_target, - GL_TEXTURE_MAX_LEVEL, texture->max_level)); + GL_TEXTURE_MAX_LEVEL, texture->max_level_set)); } -#endif /* HAVE_COGL_GL */ } void @@ -133,7 +137,8 @@ GLuint gl_handle; GLenum gl_target; - _cogl_texture_gl_maybe_update_max_level (texture, n_levels - 1); + if (texture->max_level_set != n_levels - 1) + cogl_texture_gl_set_max_level (texture, n_levels - 1); cogl_texture_get_gl_texture (texture, &gl_handle, &gl_target); diff -Nru mutter-3.36.1/cogl/cogl/driver/gl/cogl-texture-gl-private.h mutter-3.36.9/cogl/cogl/driver/gl/cogl-texture-gl-private.h --- mutter-3.36.1/cogl/cogl/driver/gl/cogl-texture-gl-private.h 2020-03-30 19:29:39.145888600 +0000 +++ mutter-3.36.9/cogl/cogl/driver/gl/cogl-texture-gl-private.h 2021-03-15 23:07:33.138504500 +0000 @@ -53,8 +53,8 @@ unsigned int mag_filter); void -_cogl_texture_gl_maybe_update_max_level (CoglTexture *texture, - int max_level); +cogl_texture_gl_set_max_level (CoglTexture *texture, + int max_level); void _cogl_texture_gl_generate_mipmaps (CoglTexture *texture); diff -Nru mutter-3.36.1/cogl/cogl/driver/gl/gl/cogl-texture-driver-gl.c mutter-3.36.9/cogl/cogl/driver/gl/gl/cogl-texture-driver-gl.c --- mutter-3.36.1/cogl/cogl/driver/gl/gl/cogl-texture-driver-gl.c 2020-03-30 19:29:39.145888600 +0000 +++ mutter-3.36.9/cogl/cogl/driver/gl/gl/cogl-texture-driver-gl.c 2021-03-15 23:07:33.139504400 +0000 @@ -255,7 +255,7 @@ * glTexImage2D first to assert that the storage for this * level exists. */ - if (texture->max_level < level) + if (texture->max_level_set < level) { ctx->glTexImage2D (gl_target, level, diff -Nru mutter-3.36.1/cogl/cogl/driver/gl/gles/cogl-texture-driver-gles.c mutter-3.36.9/cogl/cogl/driver/gl/gles/cogl-texture-driver-gles.c --- mutter-3.36.1/cogl/cogl/driver/gl/gles/cogl-texture-driver-gles.c 2020-03-30 19:29:39.145888600 +0000 +++ mutter-3.36.9/cogl/cogl/driver/gl/gles/cogl-texture-driver-gles.c 2021-03-15 23:07:33.140504400 +0000 @@ -303,7 +303,7 @@ * glTexImage2D first to assert that the storage for this * level exists. */ - if (texture->max_level < level) + if (texture->max_level_set < level) { ctx->glTexImage2D (gl_target, level, diff -Nru mutter-3.36.1/cogl/cogl-pango/cogl-pango-fontmap.c mutter-3.36.9/cogl/cogl-pango/cogl-pango-fontmap.c --- mutter-3.36.1/cogl/cogl-pango/cogl-pango-fontmap.c 2020-03-30 19:29:39.104889600 +0000 +++ mutter-3.36.9/cogl/cogl-pango/cogl-pango-fontmap.c 2021-03-15 23:07:33.096505600 +0000 @@ -74,7 +74,7 @@ cogl_pango_font_map_new (void) { PangoFontMap *fm = pango_cairo_font_map_new (); - CoglPangoFontMapPriv *priv = g_new0 (CoglPangoFontMapPriv, 1); + g_autofree CoglPangoFontMapPriv *priv = g_new0 (CoglPangoFontMapPriv, 1); _COGL_GET_CONTEXT (context, NULL); @@ -85,7 +85,7 @@ * for now. */ g_object_set_qdata_full (G_OBJECT (fm), cogl_pango_font_map_get_priv_key (), - priv, + g_steal_pointer (&priv), free_priv); return fm; diff -Nru mutter-3.36.1/debian/changelog mutter-3.36.9/debian/changelog --- mutter-3.36.1/debian/changelog 2020-04-17 01:08:01.000000000 +0000 +++ mutter-3.36.9/debian/changelog 2021-11-03 19:10:34.000000000 +0000 @@ -1,3 +1,332 @@ +mutter (3.36.9-0ubuntu0.20.04.2) focal; urgency=medium + + [ Yuan-Chen Cheng ] + * d/p/mutter-wayland-seat-race-fix.patch: + - Fix Xwayland crash Xwayland crash in gdm as screen off and touchscreen + detach (cherry picked commits — LP: #1948894) + - backported one chunk of above patch. + + -- Marco Trevisan (Treviño) Wed, 03 Nov 2021 20:10:34 +0100 + +mutter (3.36.9-0ubuntu0.20.04.1) focal; urgency=medium + + * New upstream release (LP: #1919143) + - Do not ping unmanaging windows + - Improve freezes when switching workspace + - Fix drag cancel animation when using geometry scaling + - Fix stuck icon in DND operation between X11 and wayland + - Fix restoring focus to windows using globally active input + - Fix _NET_WM_FRAME_DRAWN timestamps + - Fix unwanted position changes on window resize + - Fix device configuration not being picked up on X11 + - Fix size hints with CSD + - Disable CRTCs if there is no monitor (LP: #1905825) + - Fixed crashes + - Plugged memory leaks + + -- Marco Trevisan (Treviño) Wed, 31 Mar 2021 02:15:27 +0200 + +mutter (3.36.7+git20201123-0.20.04.1) focal; urgency=medium + + * New upstream release and git snapshot (LP: #1903230) + - Fix Night Light updates after DPMS + - Fix IM handling on X11 (LP: #1899206, thanks to Gunnar Hjalmarsson for + the initial cherry-pick) + - Fix resizing of attached modal dialogs on wayland + - Fix jumps when resizing windows using discrete steps + - Fixed crashes + - Plugged Memory leaks + - Misc. bug fixes and cleanups + * debian/libmutter-6-0.symbols: Update to match upstream changes. + No symbol is a public one + + -- Marco Trevisan (Treviño) Tue, 15 Dec 2020 04:27:46 +0100 + +mutter (3.36.6-1ubuntu0.20.04.2) focal; urgency=medium + + * xrandr-scaling: Never try to set invalid screen sizes (again!) + Looks like this change (introduced to fix LP:1889090) got lost while + rebasing previous fixes, gbp has been a bad guy this time! (LP: #1896818) + + -- Marco Trevisan (Treviño) Wed, 23 Sep 2020 22:03:53 +0200 + +mutter (3.36.6-1ubuntu0.20.04.1) focal; urgency=medium + + * Merge with debian, containing new stable release (LP: #1896332) + * debian/patches: + - Refresh patches and drop applied ones + - Don't set the font-dpi on clutter-backend-x11 (LP: #1892440) + - Cherry-pick upstream night-switch fixes for 3.36 branch + - Cherry-pick upstream fixes for handling X11 devices removal + (LP: #1558886) + * xrandr-scaling: Don't update UI scale factor on xrandr-manager creation + (LP: #1892440) + * debian/control: Revert pipewire version bumping + * Remaining changes with debian: + - debian/control: + + Update VCS flags to point to ubuntu salsa branch + - 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) Sat, 19 Sep 2020 17:21:12 +0200 + +mutter (3.36.6-1) unstable; urgency=medium + + * Team upload + * New upstream release + * Update symbols file + * d/control.in, d/rules: Enable Pipewire on Debian (but not Ubuntu). + Now that we have Pipewire 0.3, we can enable screencasting and remote + desktop support again. + + -- Simon McVittie Thu, 10 Sep 2020 12:46:31 +0100 + +mutter (3.36.5-1) unstable; urgency=medium + + * Team upload + * New upstream release + - Screencast fixes and improvements + - Fix glitches when subsurfaces extend outside the toplevel + - Improve background display in overview workspace switcher + - Fix wine copy & paste + - Plug memory leaks + * Drop patches that were applied upstream + + -- Simon McVittie Thu, 13 Aug 2020 10:19:59 +0100 + +mutter (3.36.4-1) unstable; urgency=medium + + * New upstream stable release (LP: #1887998) + - Fix crash on area screenshots with fractional scaling + - Do not paint textures of fully obscured windows + - Turn off CRTCs as well when enabling DPMS + - Improve selection support + - Use a more appropriate combine function on opaque areas + - Fix remote desktop being broken without screencast session + - Fix popovers disappearing on wayland and HiDPI + - Fixed crashes (LP: #1870867, LP: #1857947) + - Plugged memory leaks + * d/p/screen-cast-Let-the-reason-for-recording-determine-what-t.patch, + d/p/screen-cast-src-Add-flag-to-maybe_record.patch, + d/p/screen-cast-src-Fix-signedness-of-timestamp-field.patch, + d/p/screen-cast-src-Make-record-functions-return-an-error-whe.patch, + d/p/screen-cast-src-Make-the-two-record-vfuncs-more-similarly.patch, + d/p/screen-cast-src-Record-follow-up-frame-after-timeout.patch, + d/p/screen-cast-src-Remove-follow-up-timeout-source-on-disabl.patch, + d/p/screen-cast-src-Use-G_USEC_PER_SEC-instead-of-1000000.patch, + d/p/screen-cast-window-stream-src-Fix-indentation.patch: + - Import more fixes for screencasting and remote desktop + + -- Marco Trevisan (Treviño) Fri, 17 Jul 2020 21:12:56 +0200 + +mutter (3.36.4-0ubuntu0.20.04.2) focal; urgency=medium + + * xrandr-scaling: Never try to set invalid screen sizes (LP: #1889090) + + -- Marco Trevisan (Treviño) Mon, 27 Jul 2020 17:04:41 +0200 + +mutter (3.36.4-0ubuntu0.20.04.1) focal; urgency=medium + + * New upstream stable release (LP: #1887998) + - Fix crash on area screenshots with fractional scaling + - Do not paint textures of fully obscured windows + - Turn off CRTCs as well when enabling DPMS + - Improve selection support + - Use a more appropriate combine function on opaque areas + - Fix remote desktop being broken without screencast session + - Fix popovers disappearing on wayland and HiDPI + - Fixed crashes (LP: #1870867, LP: #1857947) + - Plugged memory leaks + * d/p/screen-cast-Let-the-reason-for-recording-determine-what-t.patch, + d/p/screen-cast-src-Add-flag-to-maybe_record.patch, + d/p/screen-cast-src-Fix-signedness-of-timestamp-field.patch, + d/p/screen-cast-src-Make-record-functions-return-an-error-whe.patch, + d/p/screen-cast-src-Make-the-two-record-vfuncs-more-similarly.patch, + d/p/screen-cast-src-Record-follow-up-frame-after-timeout.patch, + d/p/screen-cast-src-Remove-follow-up-timeout-source-on-disabl.patch, + d/p/screen-cast-src-Use-G_USEC_PER_SEC-instead-of-1000000.patch, + d/p/screen-cast-window-stream-src-Fix-indentation.patch: + - Import more fixes for screencasting and remote desktop + * d/p/x11-Add-support-for-fractional-scaling-using-Randr.patch: + - Don't export patch-only private symbol + * debian/libmutter-6-0.symbols: + - Remove ubuntu-only private symbol + + -- Marco Trevisan (Treviño) Mon, 20 Jul 2020 16:16:36 +0200 + +mutter (3.36.3-1) unstable; urgency=medium + + * New upstream release (LP: #1881971) + - Broadcast clipboard/primary offers + - Fix monitor screen cast on X11 + - Implement touch-mode detecation for the X11 backend (LP: #1880596) + - Drop external keyboard detection from touch-mode heuristics + - Fix leaked DMA buffers in screencasts + - Fixed crashes + + -- Marco Trevisan (Treviño) Wed, 03 Jun 2020 23:33:29 +0200 + +mutter (3.36.3-0ubuntu0.20.04.2) focal; urgency=medium + + * debian/control: + - Revert BD on adwaita-icon-theme 3.36.1-2ubuntu3. It was just temporary fix + * d/p/x11-Add-support-for-fractional-scaling-using-Randr.patch: + - Use pre-computed CRTC layout size for computing screen size (LP: #1874567, + LP: #1873403) + - Decouple the output mode from layout mode capabilities (LP: #1876894, + LP: #1886996) + - Ensure we notify CRTC changes on integer scaling changes (LP: #1876894) + - Apply proper layout monitor config when using fractional scaling + (LP: #1884754) + - Restore the fractional settings when reverting to fractional layout + (LP: #1886996) + * debian/libmutter-6-0.symbols: Add new private symbol + + -- Marco Trevisan (Treviño) Sat, 11 Jul 2020 00:55:24 +0200 + +mutter (3.36.3-0ubuntu0.20.04.1) focal; urgency=medium + + * New upstream release (LP: #1881971) + - Broadcast clipboard/primary offers + - Fix monitor screen cast on X11 + - Implement touch-mode detecation for the X11 backend (LP: #1880596) + - Drop external keyboard detection from touch-mode heuristics + - Fix leaked DMA buffers in screencasts + - Fixed crashes + * Refreshed patches + * d/p/backend-x11-Reintroduce-XInitThreads.patch: + - Dropped (merged upstream) + + -- Marco Trevisan (Treviño) Fri, 05 Jun 2020 19:29:32 +0200 + +mutter (3.36.2+12+gb425f1153-1) experimental; urgency=medium + + * Team upload + * New upstream snapshot from the gnome-3-36 branch + * d/p/backend-x11-Reintroduce-XInitThreads.patch: + Drop patch, applied upstream + + -- Simon McVittie Sat, 30 May 2020 15:12:09 +0100 + +mutter (3.36.2-3) unstable; urgency=medium + + [ Simon McVittie ] + * d/rules, d/with-temp-xdg-runtime-dir: Create temporary XDG_RUNTIME_DIR + debhelper 13.1 creates a temporary XDG_RUNTIME_DIR so we don't have to. + Unfortunately, its absolute path is sufficiently long that the path to + Mutter's Wayland display socket no longer fits in the 108 bytes allowed + by struct sockaddr_un, causing FTBFS when the tests fail. Until this is + fixed, we'll have to create our own XDG_RUNTIME_DIR with a shorter + absolute path. + Wrapping with-temp-xdg-runtime-dir around dh_auto_test doesn't work, + because dh_auto_test will reset XDG_RUNTIME_DIR, so use + meson test --wrapper to wrap with-temp-xdg-runtime-dir around the + individual tests. + (Works around: #961655) + + -- Marco Trevisan (Treviño) Wed, 27 May 2020 13:54:19 +0200 + +mutter (3.36.2-2) unstable; urgency=medium + + [ Daniel van Vugt ] + * d/p/backend-x11-Reintroduce-XInitThreads.patch: + Fix a very common crash when running in X11 (LP: #1877075) + + -- Marco Trevisan (Treviño) Tue, 26 May 2020 21:41:05 +0200 + +mutter (3.36.2-1ubuntu1~20.04.2) focal; urgency=medium + + [ Daniel van Vugt ] + * d/p/backend-x11-Reintroduce-XInitThreads.patch: + Fix a very common crash when running in X11 (LP: #1877075) + + -- Marco Trevisan (Treviño) Fri, 29 May 2020 16:19:23 +0200 + +mutter (3.36.2-1ubuntu1~20.04.1) focal; urgency=medium + + * Backport to focal (LP: #1877209) + * debian/gbp.conf: Set branch to ubuntu/focal + * debian/control: Update VCS references to focal branch + * debian/rules: Revert groovy/debian build changes as per dh 13 + + -- Marco Trevisan (Treviño) Thu, 07 May 2020 03:22:16 +0200 + +mutter (3.36.2-1ubuntu1) groovy; urgency=medium + + * Merge with debian, including new upstream release: + - Fix super key not working with secondary layout (LP: #1871913) + * xrandr-scaling: Fix compiler warnings (LP: #1874207) + * xrandr-scaling: Take care of global UI scale when restoring from config + (LP: #1825593) + * Remaining changes with debian: + - debian/control: + + Update VCS flags to point to ubuntu salsa branch + - 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) Thu, 07 May 2020 02:43:19 +0200 + +mutter (3.36.2-1) unstable; urgency=medium + + * Team upload + + [ Simon McVittie ] + * New upstream stable release + - Fix FTBFS with Wayland disabled (non-Linux kernels) + - X11 copy/paste/selection fixes (LP: #1852183) + - Fix freeze with some DisplayLink devices + - Fix a memory leak + - Synchronize shadows to server-side decorations + - Fix overview key on X11 when using multiple keyboard layouts + - Fix painting the redraw clip with the damage region + - Fix capturing with multiple stage views + - Fix screencasting of non-maximized windows (LP: #1873942) + - Various misc fixes and cleanups (LP: #1874818) + - Update translation: de + + [ Marco Trevisan (Treviño) ] + * debian/libmutter-6-0.symbols: Update + * debian/rules: Ignore build failures on riscv64 + + -- Simon McVittie Fri, 01 May 2020 11:26:55 +0100 + +mutter (3.36.1+git20200419-1) unstable; urgency=medium + + * Team upload + + [ Simon McVittie ] + * New upstream snapshot from gnome-3-36 branch (3.36.1-42-gda9eb4718) + - Fix trackball button scrolling + - Fix tiled (MST) displays + - Copy/paste fixes, particularly for large images and incremental + transfers + - Fall back to closed laptop lid configuration if no other available + (LP: #1793496) + + [ Jeremy Bicha ] + * Drop obsolete dh_strip dbgsym migration rule + * Bump debhelper-compat to 13 + - dh_missing --fail-missing is the default + - dh_auto_test has several default improvements + - dh_autoreconf isn't needed with meson + * debian/watch: Only watch for stable releases + + -- Simon McVittie Tue, 21 Apr 2020 13:46:42 +0100 + +mutter (3.36.1-4) unstable; urgency=medium + + * Team upload + * Merge changelog from unstable + * Upload to unstable (starts transition: #954422) + * Update to upstream gnome-3-36 branch, commit 3.36.1-17-g9a2471db4 + - Fix caps-lock state becoming confused on VT switch + * d/gbp.conf: Follow upstream/3.36.x branch + + -- Simon McVittie Fri, 10 Apr 2020 17:56:10 +0100 + mutter (3.36.1-3ubuntu3) focal; urgency=medium * Ignore test failures on riscv64, like s390x, to unblock @@ -37,6 +366,16 @@ -- Marco Trevisan (Treviño) Thu, 09 Apr 2020 14:40:58 +0200 +mutter (3.34.4-1) unstable; urgency=medium + + * Team upload + * d/gbp.conf: Follow debian/unstable branch + * New upstream release + * d/patches: Apply post-release fixes up to 3.34.4-5-g2709a4ffb + * Standards-Version: 4.5.0 (no changes required) + + -- Simon McVittie Tue, 25 Feb 2020 16:26:10 +0000 + mutter (3.36.1-3) experimental; urgency=medium * Team upload diff -Nru mutter-3.36.1/debian/control mutter-3.36.9/debian/control --- mutter-3.36.1/debian/control 2020-04-17 01:08:01.000000000 +0000 +++ mutter-3.36.9/debian/control 2021-11-03 19:10:34.000000000 +0000 @@ -12,6 +12,7 @@ dh-sequence-gir, dh-sequence-gnome, at-spi2-core , + adwaita-icon-theme , dbus , dmz-cursor-theme , gnome-control-center-data, @@ -79,12 +80,13 @@ Standards-Version: 4.5.0 XS-Debian-Vcs-Git: https://salsa.debian.org/gnome-team/mutter.git XS-Debian-Vcs-Browser: https://salsa.debian.org/gnome-team/mutter -Vcs-Git: https://salsa.debian.org/gnome-team/mutter.git -b ubuntu/master -Vcs-Browser: https://salsa.debian.org/gnome-team/mutter/tree/ubuntu/master +Vcs-Git: https://salsa.debian.org/gnome-team/mutter.git -b ubuntu/focal +Vcs-Browser: https://salsa.debian.org/gnome-team/mutter/tree/ubuntu/focal Package: mutter Architecture: any -Depends: gnome-settings-daemon-common, +Depends: adwaita-icon-theme, + gnome-settings-daemon-common, gsettings-desktop-schemas (>= 3.33.0), mutter-common (>= ${source:Version}), zenity, @@ -132,7 +134,8 @@ Architecture: any Multi-Arch: same Pre-Depends: ${misc:Pre-Depends} -Depends: gsettings-desktop-schemas (>= 3.33.0), +Depends: adwaita-icon-theme, + gsettings-desktop-schemas (>= 3.33.0), mutter-common (>= ${source:Version}), ${misc:Depends}, ${shlibs:Depends} diff -Nru mutter-3.36.1/debian/control.in mutter-3.36.9/debian/control.in --- mutter-3.36.1/debian/control.in 2020-04-16 20:04:59.000000000 +0000 +++ mutter-3.36.9/debian/control.in 2021-11-03 19:10:34.000000000 +0000 @@ -8,6 +8,7 @@ dh-sequence-gir, dh-sequence-gnome, at-spi2-core , + adwaita-icon-theme , dbus , dmz-cursor-theme , gnome-control-center-data, @@ -75,12 +76,13 @@ Standards-Version: 4.5.0 XS-Debian-Vcs-Git: https://salsa.debian.org/gnome-team/mutter.git XS-Debian-Vcs-Browser: https://salsa.debian.org/gnome-team/mutter -Vcs-Git: https://salsa.debian.org/gnome-team/mutter.git -b ubuntu/master -Vcs-Browser: https://salsa.debian.org/gnome-team/mutter/tree/ubuntu/master +Vcs-Git: https://salsa.debian.org/gnome-team/mutter.git -b ubuntu/focal +Vcs-Browser: https://salsa.debian.org/gnome-team/mutter/tree/ubuntu/focal Package: mutter Architecture: any -Depends: gnome-settings-daemon-common, +Depends: adwaita-icon-theme, + gnome-settings-daemon-common, gsettings-desktop-schemas (>= 3.33.0), mutter-common (>= ${source:Version}), zenity, @@ -128,7 +130,8 @@ Architecture: any Multi-Arch: same Pre-Depends: ${misc:Pre-Depends} -Depends: gsettings-desktop-schemas (>= 3.33.0), +Depends: adwaita-icon-theme, + gsettings-desktop-schemas (>= 3.33.0), mutter-common (>= ${source:Version}), ${misc:Depends}, ${shlibs:Depends} diff -Nru mutter-3.36.1/debian/gbp.conf mutter-3.36.9/debian/gbp.conf --- mutter-3.36.1/debian/gbp.conf 2020-04-16 20:04:59.000000000 +0000 +++ mutter-3.36.9/debian/gbp.conf 2021-11-03 19:10:34.000000000 +0000 @@ -1,8 +1,8 @@ [DEFAULT] pristine-tar = True -debian-branch = ubuntu/master +debian-branch = ubuntu/focal debian-tag=ubuntu/%(version)s -upstream-branch = upstream/latest +upstream-branch = upstream/3.36.x upstream-vcs-tag = %(version)s [buildpackage] diff -Nru mutter-3.36.1/debian/libmutter-6-0.symbols mutter-3.36.9/debian/libmutter-6-0.symbols --- mutter-3.36.1/debian/libmutter-6-0.symbols 2020-04-16 20:04:59.000000000 +0000 +++ mutter-3.36.9/debian/libmutter-6-0.symbols 2021-11-03 19:10:34.000000000 +0000 @@ -55,7 +55,6 @@ meta_close_dialog_response@Base 3.28.2 meta_close_dialog_response_get_type@Base 3.28.2 meta_close_dialog_show@Base 3.28.2 - meta_clutter_init@Base 3.28.2 meta_comp_effect_get_type@Base 3.28.2 meta_compositor_add_window@Base 3.28.2 meta_compositor_destroy@Base 3.28.2 @@ -526,7 +525,7 @@ meta_verify_monitors_config@Base 3.28.2 meta_virtual_modifier_get_type@Base 3.28.2 meta_warning@Base 3.28.2 - meta_wayland_actor_surface_get_actor@Base 3.35.90 + (arch=linux-any)meta_wayland_actor_surface_get_actor@Base 3.35.90 (arch=linux-any)meta_wayland_compositor_get_default@Base 3.28.2 (arch=linux-any)meta_wayland_get_wayland_display_name@Base 3.28.2 (arch=linux-any)meta_wayland_get_xwayland_display_name@Base 3.28.2 @@ -1481,7 +1480,7 @@ clutter_input_device_update@Base 3.35.90 clutter_input_device_update_from_event@Base 3.29.4 clutter_input_device_update_from_tool@Base 3.33.92 - clutter_input_focus_filter_key_event@Base 3.29.4 + clutter_input_focus_filter_event@Base 3.36.6 clutter_input_focus_get_type@Base 3.29.4 clutter_input_focus_is_focused@Base 3.29.4 clutter_input_focus_reset@Base 3.29.4 @@ -1595,6 +1594,7 @@ clutter_page_turn_effect_set_radius@Base 3.29.4 clutter_paint_context_destroy@Base 3.35.90 clutter_paint_context_get_framebuffer@Base 3.35.90 + clutter_paint_context_get_paint_flags@Base 3.36.2 clutter_paint_context_get_redraw_clip@Base 3.35.92 clutter_paint_context_get_stage_view@Base 3.35.90 clutter_paint_context_get_type@Base 3.35.90 @@ -1834,8 +1834,11 @@ clutter_stage_manager_list_stages@Base 3.29.4 clutter_stage_manager_peek_stages@Base 3.29.4 clutter_stage_new@Base 3.29.4 + clutter_stage_paint_to_buffer@Base 3.36.2 + clutter_stage_paint_to_framebuffer@Base 3.36.2 clutter_stage_queue_redraw@Base 3.29.4 clutter_stage_read_pixels@Base 3.29.4 + clutter_stage_schedule_update@Base 3.36.7+git20201123 clutter_stage_set_accept_focus@Base 3.29.4 clutter_stage_set_color@Base 3.29.4 clutter_stage_set_key_focus@Base 3.29.4 @@ -2527,6 +2530,7 @@ cogl_pipeline_set_layer_combine_constant@Base 3.29.4 cogl_pipeline_set_layer_filters@Base 3.29.4 cogl_pipeline_set_layer_matrix@Base 3.29.4 + cogl_pipeline_set_layer_max_mipmap_level@Base 3.36.6 cogl_pipeline_set_layer_null_texture@Base 3.29.4 cogl_pipeline_set_layer_point_sprite_coords_enabled@Base 3.29.4 cogl_pipeline_set_layer_texture@Base 3.29.4 diff -Nru mutter-3.36.1/debian/patches/backends-native-Translate-coordinates-of-absolute-motion-.patch mutter-3.36.9/debian/patches/backends-native-Translate-coordinates-of-absolute-motion-.patch --- mutter-3.36.1/debian/patches/backends-native-Translate-coordinates-of-absolute-motion-.patch 2020-04-16 20:04:59.000000000 +0000 +++ mutter-3.36.9/debian/patches/backends-native-Translate-coordinates-of-absolute-motion-.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,30 +0,0 @@ -From: Jonas Troeger -Date: Tue, 31 Mar 2020 22:11:37 +0200 -Subject: backends/native: Translate coordinates of absolute motion events - -The motion events of tablets for example need to be mapped on the -selected screen area if the input device is configured to use only a -part of the active logical monitor. -To achieve this behavior each motion event is transformed using the -transformation matrix set for the input device. - -Bug: https://gitlab.gnome.org/GNOME/mutter/-/issues/1118 -Origin: upstream, 3.36.2 ---- - src/backends/native/meta-seat-native.c | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/src/backends/native/meta-seat-native.c b/src/backends/native/meta-seat-native.c -index 7e0feab..9c25d4a 100644 ---- a/src/backends/native/meta-seat-native.c -+++ b/src/backends/native/meta-seat-native.c -@@ -424,6 +424,9 @@ new_absolute_motion_event (MetaSeatNative *seat, - meta_xkb_translate_state (event, seat->xkb, seat->button_state); - event->motion.x = x; - event->motion.y = y; -+ meta_input_device_native_translate_coordinates (input_device, stage, -+ &event->motion.x, -+ &event->motion.y); - event->motion.axes = axes; - clutter_event_set_device (event, seat->core_pointer); - clutter_event_set_source_device (event, input_device); diff -Nru mutter-3.36.1/debian/patches/backends-x11-Fix-access-to-WacomDevice.patch mutter-3.36.9/debian/patches/backends-x11-Fix-access-to-WacomDevice.patch --- mutter-3.36.1/debian/patches/backends-x11-Fix-access-to-WacomDevice.patch 2020-04-16 20:04:59.000000000 +0000 +++ mutter-3.36.9/debian/patches/backends-x11-Fix-access-to-WacomDevice.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,72 +0,0 @@ -From: Carlos Garnacho -Date: Tue, 7 Apr 2020 16:57:59 +0000 -Subject: backends/x11: Fix access to WacomDevice - -At some point we crossed the streams... In a short timespan we had -1f00aba92c32 merged, pushing WacomDevice to a common parent object, -and dcaa45fc0c199 implementing device grouping for X11. - -The latter did not rely on the former, and just happened to -merge/compile without issues, but would promptly trigger a crash -whenever the API would be used. - -Drop all traces of the WacomDevice internal to MetaInputDeviceX11. - -https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1183 - -(cherry picked from commit f0718c7d95820a38a54222ff362c76c2f7e0ec58) - -Origin: upstream, 3.36.2 ---- - src/backends/x11/meta-input-device-x11.c | 21 +++++++++++++-------- - 1 file changed, 13 insertions(+), 8 deletions(-) - -diff --git a/src/backends/x11/meta-input-device-x11.c b/src/backends/x11/meta-input-device-x11.c -index 2406c34..6e41ffd 100644 ---- a/src/backends/x11/meta-input-device-x11.c -+++ b/src/backends/x11/meta-input-device-x11.c -@@ -38,7 +38,6 @@ struct _MetaInputDeviceX11 - float current_y; - - #ifdef HAVE_LIBWACOM -- WacomDevice *wacom_device; - GArray *group_modes; - #endif - }; -@@ -93,13 +92,16 @@ meta_input_device_x11_is_grouped (ClutterInputDevice *device, - ClutterInputDevice *other_device) - { - #ifdef HAVE_LIBWACOM -- MetaInputDeviceX11 *device_x11 = META_INPUT_DEVICE_X11 (device); -- MetaInputDeviceX11 *other_device_x11 = META_INPUT_DEVICE_X11 (other_device); -+ WacomDevice *wacom_device, *other_wacom_device; - -- if (device_x11->wacom_device && -- other_device_x11->wacom_device && -- libwacom_compare (device_x11->wacom_device, -- other_device_x11->wacom_device, -+ wacom_device = -+ meta_input_device_get_wacom_device (META_INPUT_DEVICE (device)); -+ other_wacom_device = -+ meta_input_device_get_wacom_device (META_INPUT_DEVICE (other_device)); -+ -+ if (wacom_device && other_wacom_device && -+ libwacom_compare (wacom_device, -+ other_wacom_device, - WCOMPARE_NORMAL) == 0) - return TRUE; - #endif -@@ -413,9 +415,12 @@ pad_switch_mode (ClutterInputDevice *device, - { - MetaInputDeviceX11 *device_x11 = META_INPUT_DEVICE_X11 (device); - uint32_t n_buttons, n_modes, button_group, next_mode, i; -+ WacomDevice *wacom_device; - GList *switch_buttons = NULL; - -- n_buttons = libwacom_get_num_buttons (device_x11->wacom_device); -+ wacom_device = -+ meta_input_device_get_wacom_device (META_INPUT_DEVICE (device)); -+ n_buttons = libwacom_get_num_buttons (wacom_device); - - for (i = 0; i < n_buttons; i++) - { diff -Nru mutter-3.36.1/debian/patches/clutter-actor-Fix-pick-when-actor-is-not-allocated.patch mutter-3.36.9/debian/patches/clutter-actor-Fix-pick-when-actor-is-not-allocated.patch --- mutter-3.36.1/debian/patches/clutter-actor-Fix-pick-when-actor-is-not-allocated.patch 2020-04-16 20:04:59.000000000 +0000 +++ mutter-3.36.9/debian/patches/clutter-actor-Fix-pick-when-actor-is-not-allocated.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,30 +0,0 @@ -From: Andre Moreira Magalhaes -Date: Tue, 31 Mar 2020 21:11:19 +0000 -Subject: clutter/actor: Fix pick when actor is not allocated - -When selecting the pick regions for an actor we were not considering -whether the actor was allocated and that was causing issues where the -preferred width/height of the actor was used when deciding whether -the actor should be considered as a pick target. - -Check if the actor has a valid allocation, in addition to being mapped -and being in pick mode, in clutter_actor_should_pick_paint(). - -Forwarded: https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1169 -Applied-upstream: 3.36.2, commit:82f3bdd14e0081dff60e9fed51376fc4cbf8b201 ---- - clutter/clutter/clutter-actor.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/clutter/clutter/clutter-actor.c b/clutter/clutter/clutter-actor.c -index 56eaad6..b82d847 100644 ---- a/clutter/clutter/clutter-actor.c -+++ b/clutter/clutter/clutter-actor.c -@@ -2410,6 +2410,7 @@ clutter_actor_should_pick_paint (ClutterActor *self) - g_return_val_if_fail (CLUTTER_IS_ACTOR (self), FALSE); - - if (CLUTTER_ACTOR_IS_MAPPED (self) && -+ clutter_actor_has_allocation (self) && - (_clutter_context_get_pick_mode () == CLUTTER_PICK_ALL || - CLUTTER_ACTOR_IS_REACTIVE (self))) - return TRUE; diff -Nru mutter-3.36.1/debian/patches/clutter-backend-x11-Don-t-set-the-font-dpi-computed-on-X1.patch mutter-3.36.9/debian/patches/clutter-backend-x11-Don-t-set-the-font-dpi-computed-on-X1.patch --- mutter-3.36.1/debian/patches/clutter-backend-x11-Don-t-set-the-font-dpi-computed-on-X1.patch 1970-01-01 00:00:00.000000000 +0000 +++ mutter-3.36.9/debian/patches/clutter-backend-x11-Don-t-set-the-font-dpi-computed-on-X1.patch 2021-11-03 19:10:34.000000000 +0000 @@ -0,0 +1,51 @@ +From: =?utf-8?b?Ik1hcmNvIFRyZXZpc2FuIChUcmV2acOxbyki?= +Date: Wed, 16 Sep 2020 12:49:39 +0200 +Subject: clutter-backend-x11: Don't set the font-dpi computed on X11 + parameters + +We already set proprely the font-dpi based on user settings in +MetaSettings at each user change and as part of backend initialization, +so there's no point to set it also during x11 backend post-parsing and +using X11 values, as this may happen at later point and lead to a wrong +clutter font DPI value. + +Forwarded: https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1444 +--- + clutter/clutter/x11/clutter-backend-x11.c | 9 --------- + 1 file changed, 9 deletions(-) + +diff --git a/clutter/clutter/x11/clutter-backend-x11.c b/clutter/clutter/x11/clutter-backend-x11.c +index 697334b..c8cb880 100644 +--- a/clutter/clutter/x11/clutter-backend-x11.c ++++ b/clutter/clutter/x11/clutter-backend-x11.c +@@ -262,9 +262,7 @@ clutter_backend_x11_post_parse (ClutterBackend *backend, + GError **error) + { + ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (backend); +- ClutterSettings *settings; + Atom atoms[N_ATOM_NAMES]; +- double dpi; + + if (_foreign_dpy) + backend_x11->xdpy = _foreign_dpy; +@@ -304,8 +302,6 @@ clutter_backend_x11_post_parse (ClutterBackend *backend, + + CLUTTER_NOTE (BACKEND, "Getting the X screen"); + +- settings = clutter_settings_get_default (); +- + /* add event filter for Cogl events */ + clutter_x11_add_filter (cogl_xlib_filter, backend); + +@@ -324,11 +320,6 @@ clutter_backend_x11_post_parse (ClutterBackend *backend, + + backend_x11->display_name = g_strdup (clutter_display_name); + +- dpi = (((double) DisplayHeight (backend_x11->xdpy, backend_x11->xscreen_num) * 25.4) +- / (double) DisplayHeightMM (backend_x11->xdpy, backend_x11->xscreen_num)); +- +- g_object_set (settings, "font-dpi", (int) dpi * 1024, NULL); +- + /* create XSETTINGS client */ + backend_x11->xsettings = + _clutter_xsettings_client_new (backend_x11->xdpy, diff -Nru mutter-3.36.1/debian/patches/clutter-click-action-Do-not-process-captured-event-if-act.patch mutter-3.36.9/debian/patches/clutter-click-action-Do-not-process-captured-event-if-act.patch --- mutter-3.36.1/debian/patches/clutter-click-action-Do-not-process-captured-event-if-act.patch 2020-04-16 20:04:59.000000000 +0000 +++ mutter-3.36.9/debian/patches/clutter-click-action-Do-not-process-captured-event-if-act.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,36 +0,0 @@ -From: Andre Moreira Magalhaes -Date: Thu, 2 Apr 2020 16:12:43 +0000 -Subject: clutter/click-action: Do not process captured event if action is - disabled - -Disabling a click action after a button-press but before a -button-release is captured makes ClutterClickAction connect to -captured-event and never disconnect. - -This change fixes it by making sure the captured-event is only -processed if the action is still enabled, otherwise releasing -the action (reset state) and propagating the event. - -Forwarded: https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1170 -Applied-upstream: 3.36.2, commit:95c1baf3d18fe8e50de402b7af4c29d9ae993d19 ---- - clutter/clutter/clutter-click-action.c | 6 ++++++ - 1 file changed, 6 insertions(+) - -diff --git a/clutter/clutter/clutter-click-action.c b/clutter/clutter/clutter-click-action.c -index 6b523b0..cb35d72 100644 ---- a/clutter/clutter/clutter-click-action.c -+++ b/clutter/clutter/clutter-click-action.c -@@ -346,6 +346,12 @@ on_captured_event (ClutterActor *stage, - ClutterModifierType modifier_state; - gboolean has_button = TRUE; - -+ if (!clutter_actor_meta_get_enabled (CLUTTER_ACTOR_META (action))) -+ { -+ clutter_click_action_release (action); -+ return CLUTTER_EVENT_PROPAGATE; -+ } -+ - actor = clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (action)); - - switch (clutter_event_type (event)) diff -Nru mutter-3.36.1/debian/patches/clutter-master-clock-default-Sync-timelines-to-hardware-v.patch mutter-3.36.9/debian/patches/clutter-master-clock-default-Sync-timelines-to-hardware-v.patch --- mutter-3.36.1/debian/patches/clutter-master-clock-default-Sync-timelines-to-hardware-v.patch 2020-04-16 20:04:59.000000000 +0000 +++ mutter-3.36.9/debian/patches/clutter-master-clock-default-Sync-timelines-to-hardware-v.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,71 +0,0 @@ -From: Daniel van Vugt -Date: Tue, 13 Aug 2019 18:03:26 +0800 -Subject: clutter/master-clock-default: Sync timelines to hardware vsync - -Previously clutter timelines advanced according to `g_source_get_time`. -But that meant the spatial stepping of animations was visibly sensitive to -any irregularities in the main loop. It also represented a time older [1] -than the intended presentation time of each frame. - -Now we instead use `master_clock_get_next_presentation_time`. This ensures -we get the smoothness of hardware vsync as well as being closer to the -actual presentation time. - -This means, for example, backends like Xorg that move the hardware cursor -independently of repaints will have their animations more closely matching -the hardware cursor position. So the cursor appears to stick more closely -when dragging windows or on the lock screen etc. - -[1] "older" = (refresh_interval - sync_delay) = ~14ms for 60Hz - -Bug: https://gitlab.gnome.org/GNOME/mutter/issues/25 -Forwarded: https://gitlab.gnome.org/GNOME/mutter/merge_requests/724 -Applied-upstream: 3.36.2, commit:6f094bd399f4197e7036d8306337b4b0ee72ca65 ---- - clutter/clutter/clutter-master-clock-default.c | 26 +++++++++++++++++++++++++- - 1 file changed, 25 insertions(+), 1 deletion(-) - -diff --git a/clutter/clutter/clutter-master-clock-default.c b/clutter/clutter/clutter-master-clock-default.c -index 8d50ab8..ac55f1b 100644 ---- a/clutter/clutter/clutter-master-clock-default.c -+++ b/clutter/clutter/clutter-master-clock-default.c -@@ -190,6 +190,26 @@ master_clock_get_swap_wait_time (ClutterMasterClockDefault *master_clock) - } - } - -+static int64_t -+master_clock_get_next_presentation_time (ClutterMasterClockDefault *master_clock) -+{ -+ ClutterStageManager *stage_manager = clutter_stage_manager_get_default (); -+ const GSList *stages, *l; -+ int64_t earliest = -1; -+ -+ stages = clutter_stage_manager_peek_stages (stage_manager); -+ -+ for (l = stages; l != NULL; l = l->next) -+ { -+ gint64 t = _clutter_stage_get_next_presentation_time (l->data); -+ -+ if (earliest == -1 || (t != -1 && t < earliest)) -+ earliest = t; -+ } -+ -+ return earliest; -+} -+ - static void - master_clock_schedule_stage_updates (ClutterMasterClockDefault *master_clock) - { -@@ -466,7 +486,11 @@ clutter_clock_dispatch (GSource *source, - COGL_TRACE_BEGIN (ClutterMasterClockTick, "Master Clock (tick)"); - - /* Get the time to use for this frame */ -- master_clock->cur_tick = g_source_get_time (source); -+ master_clock->cur_tick = master_clock_get_next_presentation_time (master_clock); -+ -+ /* On the first frame the backend might not have an answer */ -+ if (master_clock->cur_tick <= 0) -+ master_clock->cur_tick = g_source_get_time (source); - - #ifdef CLUTTER_ENABLE_DEBUG - master_clock->remaining_budget = master_clock->frame_budget; diff -Nru mutter-3.36.1/debian/patches/clutter-stage-Add-API-to-get_next_presentation_time.patch mutter-3.36.9/debian/patches/clutter-stage-Add-API-to-get_next_presentation_time.patch --- mutter-3.36.1/debian/patches/clutter-stage-Add-API-to-get_next_presentation_time.patch 2020-04-16 20:04:59.000000000 +0000 +++ mutter-3.36.9/debian/patches/clutter-stage-Add-API-to-get_next_presentation_time.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,178 +0,0 @@ -From: Daniel van Vugt -Date: Tue, 13 Aug 2019 17:33:19 +0800 -Subject: clutter/stage: Add API to get_next_presentation_time - -Forwarded: https://gitlab.gnome.org/GNOME/mutter/merge_requests/724 -Applied-upstream: 3.36.2, commit:2c805524b49150793fe97908cb309d9b8c52f8ad ---- - clutter/clutter/clutter-stage-private.h | 1 + - clutter/clutter/clutter-stage-window.c | 16 ++++++++++++++++ - clutter/clutter/clutter-stage-window.h | 4 ++++ - clutter/clutter/clutter-stage.c | 15 +++++++++++++++ - clutter/clutter/cogl/clutter-stage-cogl.c | 32 ++++++++++++++++++++++++++++++- - clutter/clutter/cogl/clutter-stage-cogl.h | 1 + - 6 files changed, 68 insertions(+), 1 deletion(-) - -diff --git a/clutter/clutter/clutter-stage-private.h b/clutter/clutter/clutter-stage-private.h -index c8c1ef3..a8abd05 100644 ---- a/clutter/clutter/clutter-stage-private.h -+++ b/clutter/clutter/clutter-stage-private.h -@@ -78,6 +78,7 @@ void _clutter_stage_schedule_update (ClutterStage *stage); - gint64 _clutter_stage_get_update_time (ClutterStage *stage); - void _clutter_stage_clear_update_time (ClutterStage *stage); - gboolean _clutter_stage_has_full_redraw_queued (ClutterStage *stage); -+int64_t _clutter_stage_get_next_presentation_time (ClutterStage *stage); - - void clutter_stage_log_pick (ClutterStage *stage, - const graphene_point_t *vertices, -diff --git a/clutter/clutter/clutter-stage-window.c b/clutter/clutter/clutter-stage-window.c -index 3c80124..a3782a1 100644 ---- a/clutter/clutter/clutter-stage-window.c -+++ b/clutter/clutter/clutter-stage-window.c -@@ -178,6 +178,22 @@ _clutter_stage_window_clear_update_time (ClutterStageWindow *window) - iface->clear_update_time (window); - } - -+int64_t -+_clutter_stage_window_get_next_presentation_time (ClutterStageWindow *window) -+{ -+ ClutterStageWindowInterface *iface; -+ -+ g_return_val_if_fail (CLUTTER_IS_STAGE_WINDOW (window), 0); -+ -+ iface = CLUTTER_STAGE_WINDOW_GET_IFACE (window); -+ -+ /* If not implemented then just revert to the old behaviour... */ -+ if (iface->get_next_presentation_time == NULL) -+ return _clutter_stage_window_get_update_time (window); -+ -+ return iface->get_next_presentation_time (window); -+} -+ - void - _clutter_stage_window_set_accept_focus (ClutterStageWindow *window, - gboolean accept_focus) -diff --git a/clutter/clutter/clutter-stage-window.h b/clutter/clutter/clutter-stage-window.h -index eb52941..78d15b7 100644 ---- a/clutter/clutter/clutter-stage-window.h -+++ b/clutter/clutter/clutter-stage-window.h -@@ -61,6 +61,8 @@ struct _ClutterStageWindowInterface - GList *(* get_views) (ClutterStageWindow *stage_window); - int64_t (* get_frame_counter) (ClutterStageWindow *stage_window); - void (* finish_frame) (ClutterStageWindow *stage_window); -+ -+ int64_t (* get_next_presentation_time) (ClutterStageWindow *stage_window); - }; - - ClutterActor * _clutter_stage_window_get_wrapper (ClutterStageWindow *window); -@@ -101,6 +103,8 @@ void _clutter_stage_window_finish_frame (ClutterStageWin - - int64_t _clutter_stage_window_get_frame_counter (ClutterStageWindow *window); - -+int64_t _clutter_stage_window_get_next_presentation_time (ClutterStageWindow *window); -+ - G_END_DECLS - - #endif /* __CLUTTER_STAGE_WINDOW_H__ */ -diff --git a/clutter/clutter/clutter-stage.c b/clutter/clutter/clutter-stage.c -index 07ba9df..fb73a02 100644 ---- a/clutter/clutter/clutter-stage.c -+++ b/clutter/clutter/clutter-stage.c -@@ -3751,6 +3751,21 @@ _clutter_stage_clear_update_time (ClutterStage *stage) - _clutter_stage_window_clear_update_time (stage_window); - } - -+int64_t -+_clutter_stage_get_next_presentation_time (ClutterStage *stage) -+{ -+ ClutterStageWindow *stage_window; -+ -+ if (CLUTTER_ACTOR_IN_DESTRUCTION (stage)) -+ return 0; -+ -+ stage_window = _clutter_stage_get_window (stage); -+ if (stage_window == NULL) -+ return 0; -+ -+ return _clutter_stage_window_get_next_presentation_time (stage_window); -+} -+ - ClutterPaintVolume * - _clutter_stage_paint_volume_stack_allocate (ClutterStage *stage) - { -diff --git a/clutter/clutter/cogl/clutter-stage-cogl.c b/clutter/clutter/cogl/clutter-stage-cogl.c -index d48e976..28b3345 100644 ---- a/clutter/clutter/cogl/clutter-stage-cogl.c -+++ b/clutter/clutter/cogl/clutter-stage-cogl.c -@@ -235,7 +235,12 @@ clutter_stage_cogl_schedule_update (ClutterStageWindow *stage_window, - stage_cogl->update_time = next_presentation_time - max_render_time_allowed; - - if (stage_cogl->update_time == stage_cogl->last_update_time) -- stage_cogl->update_time = stage_cogl->last_update_time + refresh_interval; -+ { -+ stage_cogl->update_time += refresh_interval; -+ next_presentation_time += refresh_interval; -+ } -+ -+ stage_cogl->next_presentation_time = next_presentation_time; - } - - static gint64 -@@ -256,6 +261,29 @@ clutter_stage_cogl_clear_update_time (ClutterStageWindow *stage_window) - - stage_cogl->last_update_time = stage_cogl->update_time; - stage_cogl->update_time = -1; -+ stage_cogl->next_presentation_time = -1; -+} -+ -+static int64_t -+clutter_stage_cogl_get_next_presentation_time (ClutterStageWindow *stage_window) -+{ -+ ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window); -+ int64_t now = g_get_monotonic_time (); -+ -+ if (stage_cogl->next_presentation_time > 0 && -+ stage_cogl->next_presentation_time <= now) -+ { -+ CLUTTER_NOTE (BACKEND, -+ "Missed some frames. Something blocked for over " -+ "%" G_GINT64_FORMAT "ms.", -+ (now - stage_cogl->next_presentation_time) / 1000); -+ -+ stage_cogl->update_time = -1; -+ clutter_stage_cogl_schedule_update (stage_window, -+ stage_cogl->last_sync_delay); -+ } -+ -+ return stage_cogl->next_presentation_time; - } - - static ClutterActor * -@@ -1008,6 +1036,7 @@ clutter_stage_window_iface_init (ClutterStageWindowInterface *iface) - iface->schedule_update = clutter_stage_cogl_schedule_update; - iface->get_update_time = clutter_stage_cogl_get_update_time; - iface->clear_update_time = clutter_stage_cogl_clear_update_time; -+ iface->get_next_presentation_time = clutter_stage_cogl_get_next_presentation_time; - iface->redraw = clutter_stage_cogl_redraw; - } - -@@ -1053,6 +1082,7 @@ _clutter_stage_cogl_init (ClutterStageCogl *stage) - stage->refresh_rate = 0.0; - - stage->update_time = -1; -+ stage->next_presentation_time = -1; - } - - static void -diff --git a/clutter/clutter/cogl/clutter-stage-cogl.h b/clutter/clutter/cogl/clutter-stage-cogl.h -index 1eaa02e..634f856 100644 ---- a/clutter/clutter/cogl/clutter-stage-cogl.h -+++ b/clutter/clutter/cogl/clutter-stage-cogl.h -@@ -48,6 +48,7 @@ struct _ClutterStageCogl - gint64 last_presentation_time; - gint64 update_time; - int64_t last_update_time; -+ int64_t next_presentation_time; - - /* We only enable clipped redraws after 2 frames, since we've seen - * a lot of drivers can struggle to get going and may output some diff -Nru mutter-3.36.1/debian/patches/clutter-stage-Don-t-assume-stage-relayouts-reallocate-eve.patch mutter-3.36.9/debian/patches/clutter-stage-Don-t-assume-stage-relayouts-reallocate-eve.patch --- mutter-3.36.1/debian/patches/clutter-stage-Don-t-assume-stage-relayouts-reallocate-eve.patch 2020-04-16 20:04:59.000000000 +0000 +++ mutter-3.36.9/debian/patches/clutter-stage-Don-t-assume-stage-relayouts-reallocate-eve.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,67 +0,0 @@ -From: =?utf-8?q?Jonas_Dre=C3=9Fler?= -Date: Fri, 3 Apr 2020 08:40:46 +0000 -Subject: clutter/stage: Don't assume stage relayouts reallocate everything - -With the introduction of "shallow" relayouts, we are now able to enter -allocation cycles not only at the stage but also deeper down the -hierarchy if we know an actors allocation isn't affected by its children -since the NO_LAYOUT flag is set. - -Now that means when queuing relayouts it's possible that -`priv->needs_allocation` gets set to TRUE for some actors down the -hierarchy, but not for actors higher up in the hierarchy. An actor tree -where that happens could look like that: - -stage -> container -> container2 (NO_LAYOUT) -> textActor - -With that tree, if the "textActor" queues a relayout, "container2" will -be added to the relayout hashtable of the stage and the actors "stage" -and "container" will have `priv->needs_allocation` set to FALSE. - -Now if another relayout on the stage actor is queued, -`clutter_stage_queue_actor_relayout()` currently removes all the other -hashtable entries in favour of the stage entry, (wrongly) assuming that -will allocate everything. It doesn't allocate everything because in the -example above "container" has `priv->needs_allocation` set to FALSE, -which makes clutter_actor_allocate() return early before allocating its -children, so in the end "container2" will never get a new allocation. - -To fix this, stop flushing the relayout hashtable when queuing a -stage-relayout and still add new entries to the hashtable if a stage -relayout is already queued to make sure we still go through all the -previously queued "shallow" relayouts. That shouldn't hurt performance, -too, because as soon as an actor got allocated once, it doesn't need an -allocation anymore and should bail out in clutter_actor_allocate() as -long as it's absolute position didn't change. - -Fixes https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/2538 - -https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1173 - -(cherry picked from commit e74c2e42cf3dc744aaa53cb5a683138425cda9b6) - -Origin: upstream, 3.36.2 ---- - clutter/clutter/clutter-stage.c | 6 ------ - 1 file changed, 6 deletions(-) - -diff --git a/clutter/clutter/clutter-stage.c b/clutter/clutter/clutter-stage.c -index fb73a02..4587786 100644 ---- a/clutter/clutter/clutter-stage.c -+++ b/clutter/clutter/clutter-stage.c -@@ -1320,15 +1320,9 @@ clutter_stage_queue_actor_relayout (ClutterStage *stage, - { - ClutterStagePrivate *priv = stage->priv; - -- if (g_hash_table_contains (priv->pending_relayouts, stage)) -- return; -- - if (g_hash_table_size (priv->pending_relayouts) == 0) - _clutter_stage_schedule_update (stage); - -- if (actor == (ClutterActor *) stage) -- g_hash_table_remove_all (priv->pending_relayouts); -- - g_hash_table_add (priv->pending_relayouts, g_object_ref (actor)); - priv->pending_relayouts_version++; - } diff -Nru mutter-3.36.1/debian/patches/cogl-Defend-against-empty-or-unallocated-framebuffers.patch mutter-3.36.9/debian/patches/cogl-Defend-against-empty-or-unallocated-framebuffers.patch --- mutter-3.36.1/debian/patches/cogl-Defend-against-empty-or-unallocated-framebuffers.patch 2020-04-16 20:04:59.000000000 +0000 +++ mutter-3.36.9/debian/patches/cogl-Defend-against-empty-or-unallocated-framebuffers.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,37 +0,0 @@ -From: Simon McVittie -Date: Thu, 2 Apr 2020 19:30:59 +0100 -Subject: cogl: Defend against empty or unallocated framebuffers - -It isn't immediately obvious that this is impossible, because there's some -"action at a distance" going on with framebuffers that have their size -set lazily, after their textures get allocated; so let's make this a -critical warning rather than crashing. - -In particular, this works around a crash when gnome-shell tries to blur a -background that hasn't yet had any space allocated for it - which it seems -is really an actor layout bug, but more robustness seems good to have. - -Workaround for . - -Forwarded: https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1172 -Signed-off-by: Simon McVittie -Applied-upstream: origin, 3.36.2, commit:e339a57ddf87de42e8171a935a7617cd2acf7ef6 ---- - cogl/cogl/driver/gl/cogl-framebuffer-gl.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/cogl/cogl/driver/gl/cogl-framebuffer-gl.c b/cogl/cogl/driver/gl/cogl-framebuffer-gl.c -index 2848d71..e4d215e 100644 ---- a/cogl/cogl/driver/gl/cogl-framebuffer-gl.c -+++ b/cogl/cogl/driver/gl/cogl-framebuffer-gl.c -@@ -132,8 +132,8 @@ _cogl_framebuffer_gl_flush_viewport_state (CoglFramebuffer *framebuffer) - { - float gl_viewport_y; - -- g_assert (framebuffer->viewport_width >=0 && -- framebuffer->viewport_height >=0); -+ g_return_if_fail (framebuffer->viewport_width >= 0); -+ g_return_if_fail (framebuffer->viewport_height >= 0); - - /* Convert the Cogl viewport y offset to an OpenGL viewport y offset - * NB: OpenGL defines its window and viewport origins to be bottom diff -Nru mutter-3.36.1/debian/patches/cogl-Don-t-allow-creating-sized-textures-with-0-pixels.patch mutter-3.36.9/debian/patches/cogl-Don-t-allow-creating-sized-textures-with-0-pixels.patch --- mutter-3.36.1/debian/patches/cogl-Don-t-allow-creating-sized-textures-with-0-pixels.patch 2020-04-16 20:04:59.000000000 +0000 +++ mutter-3.36.9/debian/patches/cogl-Don-t-allow-creating-sized-textures-with-0-pixels.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,36 +0,0 @@ -From: Simon McVittie -Date: Thu, 2 Apr 2020 19:30:14 +0100 -Subject: cogl: Don't allow creating sized textures with 0 pixels - -A texture with no pixels isn't a useful thing to have, and breaks -assumptions elsewhere. For example, CoglFramebuffer assumes that after -a texture has been allocated, it will have width and height both greater -than 0. - -In particular, this works around a crash when gnome-shell tries to blur a -background that hasn't yet had any space allocated for it - which it seems -is really an actor layout bug, but more robustness seems good to have. - -Workaround for . - -Forwarded: https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1172 -Signed-off-by: Simon McVittie -Applied-upstream: 3.36.2, commit:e3b2b90c72f72f9bf4a99add15829bf275fbe1a7 ---- - cogl/cogl/cogl-texture-2d.c | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/cogl/cogl/cogl-texture-2d.c b/cogl/cogl/cogl-texture-2d.c -index 21a3c3f..a99cbb3 100644 ---- a/cogl/cogl/cogl-texture-2d.c -+++ b/cogl/cogl/cogl-texture-2d.c -@@ -121,6 +121,9 @@ cogl_texture_2d_new_with_size (CoglContext *ctx, - { - CoglTextureLoader *loader; - -+ g_return_val_if_fail (width >= 1, NULL); -+ g_return_val_if_fail (height >= 1, NULL); -+ - loader = _cogl_texture_create_loader (); - loader->src_type = COGL_TEXTURE_SOURCE_TYPE_SIZED; - loader->src.sized.width = width; diff -Nru mutter-3.36.1/debian/patches/debian/synaptics-support.patch mutter-3.36.9/debian/patches/debian/synaptics-support.patch --- mutter-3.36.1/debian/patches/debian/synaptics-support.patch 2020-04-16 20:04:59.000000000 +0000 +++ mutter-3.36.9/debian/patches/debian/synaptics-support.patch 2021-11-03 19:10:34.000000000 +0000 @@ -260,10 +260,10 @@ switch (mode) { diff --git a/src/backends/x11/meta-seat-x11.c b/src/backends/x11/meta-seat-x11.c -index e6e9968..587a6ca 100644 +index 491b82f..ff028bf 100644 --- a/src/backends/x11/meta-seat-x11.c +++ b/src/backends/x11/meta-seat-x11.c -@@ -243,7 +243,8 @@ is_touch_device (XIAnyClassInfo **classes, +@@ -248,7 +248,8 @@ is_touch_device (XIAnyClassInfo **classes, } static gboolean @@ -273,7 +273,7 @@ { gulong nitems, bytes_after; uint32_t *data = NULL; -@@ -251,7 +252,7 @@ is_touchpad_device (XIDeviceInfo *info) +@@ -256,7 +257,7 @@ is_touchpad_device (XIDeviceInfo *info) Atom type; Atom prop; @@ -282,7 +282,7 @@ if (prop == None) return FALSE; -@@ -272,6 +273,13 @@ is_touchpad_device (XIDeviceInfo *info) +@@ -277,6 +278,13 @@ is_touchpad_device (XIDeviceInfo *info) return TRUE; } diff -Nru mutter-3.36.1/debian/patches/debian/tests-Tag-closed-transient-no-input-tests-as-flaky.patch mutter-3.36.9/debian/patches/debian/tests-Tag-closed-transient-no-input-tests-as-flaky.patch --- mutter-3.36.1/debian/patches/debian/tests-Tag-closed-transient-no-input-tests-as-flaky.patch 2020-04-16 20:04:59.000000000 +0000 +++ mutter-3.36.9/debian/patches/debian/tests-Tag-closed-transient-no-input-tests-as-flaky.patch 2021-11-03 19:10:34.000000000 +0000 @@ -1,5 +1,5 @@ From: Iain Lane -Date: Wed, 14 Aug 2019 16:08:48 +0100 +Date: Wed, 14 Aug 2019 17:08:48 +0200 Subject: tests: Tag 'closed-transient-no-input' tests as flaky Then test runners can run these ones non-fatally. diff -Nru mutter-3.36.1/debian/patches/meson-add-back-default_driver-option.patch mutter-3.36.9/debian/patches/meson-add-back-default_driver-option.patch --- mutter-3.36.1/debian/patches/meson-add-back-default_driver-option.patch 2020-04-16 20:04:59.000000000 +0000 +++ mutter-3.36.9/debian/patches/meson-add-back-default_driver-option.patch 2021-11-03 19:10:34.000000000 +0000 @@ -44,7 +44,7 @@ input: 'cogl-config.h.meson', output: 'cogl-config.h', diff --git a/meson.build b/meson.build -index 3b8d519..ec20965 100644 +index 637173a..46cfbef 100644 --- a/meson.build +++ b/meson.build @@ -222,6 +222,8 @@ if have_wayland_eglstream @@ -65,7 +65,7 @@ ' gudev.................... ' + have_libgudev.to_string(), ' Wacom.................... ' + have_libwacom.to_string(), diff --git a/meson_options.txt b/meson_options.txt -index 75a1961..8b1088d 100644 +index 655ef43..b4c0375 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -158,3 +158,9 @@ option('xwayland_initfd', diff -Nru mutter-3.36.1/debian/patches/monitor-config-manager-Fallback-to-closed-laptop-lid-conf.patch mutter-3.36.9/debian/patches/monitor-config-manager-Fallback-to-closed-laptop-lid-conf.patch --- mutter-3.36.1/debian/patches/monitor-config-manager-Fallback-to-closed-laptop-lid-conf.patch 2020-04-16 20:04:59.000000000 +0000 +++ mutter-3.36.9/debian/patches/monitor-config-manager-Fallback-to-closed-laptop-lid-conf.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,69 +0,0 @@ -From: =?utf-8?b?Ik1hcmNvIFRyZXZpc2FuIChUcmV2acOxbyki?= -Date: Thu, 16 Apr 2020 00:28:05 +0200 -Subject: monitor-config-manager: Fallback to closed laptop lid configuration - -When closing the lid of a laptop, we reconfigure all the monitors in order -to update the CRTCs and (if enabled) the global UI scaling factor. - -To do this, we try first to reuse the current configuration for the usable -monitors, but if we have only monitor enabled and this one is on the laptop -lid we just end up creating a new configuration where the primary monitor is -the laptop one (as per find_primary_monitor() in MetaMonitorConfigManager), -but ignoring the user parameters. - -In case the user selected a different resolution / scaling compared to the -default one, while the laptop lid is closed we might change the monitors -layout, causing applications to rescale or reposition. - -To avoid this, when creating the monitors configuration from the current -current state, in case we have only one monitor available and that one is -the laptop panel, let's just reuse this configuration. - -https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1200 ---- - src/backends/meta-monitor-config-manager.c | 18 +++++++++++++++--- - 1 file changed, 15 insertions(+), 3 deletions(-) - -diff --git a/src/backends/meta-monitor-config-manager.c b/src/backends/meta-monitor-config-manager.c -index 5739ca1..6e31432 100644 ---- a/src/backends/meta-monitor-config-manager.c -+++ b/src/backends/meta-monitor-config-manager.c -@@ -443,23 +443,35 @@ MetaMonitorsConfigKey * - meta_create_monitors_config_key_for_current_state (MetaMonitorManager *monitor_manager) - { - MetaMonitorsConfigKey *config_key; -+ MetaMonitorSpec *laptop_monitor_spec; - GList *l; - GList *monitor_specs; - -+ laptop_monitor_spec = NULL; - monitor_specs = NULL; - for (l = monitor_manager->monitors; l; l = l->next) - { - MetaMonitor *monitor = l->data; - MetaMonitorSpec *monitor_spec; - -- if (meta_monitor_is_laptop_panel (monitor) && -- is_lid_closed (monitor_manager)) -- continue; -+ if (meta_monitor_is_laptop_panel (monitor)) -+ { -+ laptop_monitor_spec = meta_monitor_get_spec (monitor); -+ -+ if (is_lid_closed (monitor_manager)) -+ continue; -+ } - - monitor_spec = meta_monitor_spec_clone (meta_monitor_get_spec (monitor)); - monitor_specs = g_list_prepend (monitor_specs, monitor_spec); - } - -+ if (!monitor_specs && laptop_monitor_spec) -+ { -+ monitor_specs = -+ g_list_prepend (NULL, meta_monitor_spec_clone (laptop_monitor_spec)); -+ } -+ - if (!monitor_specs) - return NULL; - diff -Nru mutter-3.36.1/debian/patches/mutter-wayland-seat-race-fix.patch mutter-3.36.9/debian/patches/mutter-wayland-seat-race-fix.patch --- mutter-3.36.1/debian/patches/mutter-wayland-seat-race-fix.patch 1970-01-01 00:00:00.000000000 +0000 +++ mutter-3.36.9/debian/patches/mutter-wayland-seat-race-fix.patch 2021-11-03 19:10:34.000000000 +0000 @@ -0,0 +1,204 @@ +From: "Y.C Cheng" +Date: Mon, 1 Nov 2021 12:54:08 +0800 +Subject: mutter-wayland-seat-race-fix + +Back ported one of the chunk of the patch from upstream to works with +mutter 3.38.4 and 3.36.9. + +commit 20bb8bf502ae4afde96a35d4637382d893efc029 +Author: Olivier Fourdan +Date: Tue Nov 28 10:54:08 2017 +0100 + + wayland: Avoid a race in wl_seat capabilities + + The way wl_seat capabilities work, by notifying clients of capabilities + changes, and clients consequently requesting the relevant interface + objects (pointer, keyboard, touch) is inherently racy. + + On quick VT changes for example, capabilities on the seat will be added + and removed, and by the time the client receives the capability change + notification and requests the relevant keyboard, pointer or touch, + another VT switch might have occurred and the wl_pointer, wl_keyboard or + wl_touch already destroyed, leading to a protocol error which kills the + client. + + To avoid this, create the objects when requested regardless of the + capabilities. + + Closes: https://gitlab.gnome.org/GNOME/mutter/-/issues/1797 + Related: https://bugzilla.gnome.org/show_bug.cgi?id=790932 + Part-of: + +Origin: https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/77 +Bug-GNOME: https://gitlab.gnome.org/GNOME/mutter/-/issues/1797 +Bug-Ubuntu: https://launchpad.net/bugs/1948894 +Forwarded: yes +Last-Update: 2021-11-01 +--- + src/wayland/meta-wayland-pointer.c | 45 +++++++++++++++++++++++++++++++------- + src/wayland/meta-wayland-seat.c | 9 +++----- + src/wayland/meta-wayland-touch.c | 8 ------- + 3 files changed, 40 insertions(+), 22 deletions(-) + +diff --git a/src/wayland/meta-wayland-pointer.c b/src/wayland/meta-wayland-pointer.c +index d300852..a24a049 100644 +--- a/src/wayland/meta-wayland-pointer.c ++++ b/src/wayland/meta-wayland-pointer.c +@@ -110,7 +110,7 @@ meta_wayland_pointer_client_new (void) + } + + static void +-meta_wayland_pointer_client_free (MetaWaylandPointerClient *pointer_client) ++meta_wayland_pointer_make_resources_inert (MetaWaylandPointerClient *pointer_client) + { + struct wl_resource *resource, *next; + +@@ -138,10 +138,25 @@ meta_wayland_pointer_client_free (MetaWaylandPointerClient *pointer_client) + wl_list_remove (wl_resource_get_link (resource)); + wl_list_init (wl_resource_get_link (resource)); + } ++} + ++static void ++meta_wayland_pointer_client_free (MetaWaylandPointerClient *pointer_client) ++{ ++ meta_wayland_pointer_make_resources_inert (pointer_client); + g_slice_free (MetaWaylandPointerClient, pointer_client); + } + ++static void ++make_resources_inert_foreach (gpointer key, ++ gpointer value, ++ gpointer data) ++{ ++ MetaWaylandPointerClient *pointer_client = value; ++ ++ meta_wayland_pointer_make_resources_inert (pointer_client); ++} ++ + static gboolean + meta_wayland_pointer_client_is_empty (MetaWaylandPointerClient *pointer_client) + { +@@ -155,8 +170,6 @@ MetaWaylandPointerClient * + meta_wayland_pointer_get_pointer_client (MetaWaylandPointer *pointer, + struct wl_client *client) + { +- if (!pointer->pointer_clients) +- return NULL; + return g_hash_table_lookup (pointer->pointer_clients, client); + } + +@@ -501,10 +514,6 @@ meta_wayland_pointer_enable (MetaWaylandPointer *pointer) + MetaCursorTracker *cursor_tracker = meta_backend_get_cursor_tracker (backend); + ClutterSeat *clutter_seat; + +- pointer->pointer_clients = +- g_hash_table_new_full (NULL, NULL, NULL, +- (GDestroyNotify) meta_wayland_pointer_client_free); +- + pointer->cursor_surface = NULL; + + clutter_seat = clutter_backend_get_default_seat (clutter_get_default_backend ()); +@@ -534,6 +543,10 @@ meta_wayland_pointer_disable (MetaWaylandPointer *pointer) + ClutterBackend *clutter_backend = clutter_get_default_backend (); + ClutterSeat *clutter_seat = clutter_backend_get_default_seat (clutter_backend); + ++ g_hash_table_foreach (pointer->pointer_clients, ++ make_resources_inert_foreach, ++ NULL); ++ + g_signal_handlers_disconnect_by_func (cursor_tracker, + (gpointer) meta_wayland_pointer_on_cursor_changed, + pointer); +@@ -557,7 +570,6 @@ meta_wayland_pointer_disable (MetaWaylandPointer *pointer) + meta_wayland_pointer_set_focus (pointer, NULL); + meta_wayland_pointer_set_current (pointer, NULL); + +- g_clear_pointer (&pointer->pointer_clients, g_hash_table_unref); + pointer->cursor_surface = NULL; + } + +@@ -1373,11 +1385,28 @@ meta_wayland_pointer_init (MetaWaylandPointer *pointer) + pointer->default_grab.interface = &default_pointer_grab_interface; + pointer->default_grab.pointer = pointer; + pointer->grab = &pointer->default_grab; ++ pointer->pointer_clients = ++ g_hash_table_new_full (NULL, NULL, NULL, ++ (GDestroyNotify) meta_wayland_pointer_client_free); ++} ++ ++static void ++meta_wayland_pointer_finalize (GObject *object) ++{ ++ MetaWaylandPointer *pointer = META_WAYLAND_POINTER (object); ++ ++ g_clear_pointer (&pointer->pointer_clients, g_hash_table_unref); ++ ++ G_OBJECT_CLASS (meta_wayland_pointer_parent_class)->finalize (object); + } + + static void + meta_wayland_pointer_class_init (MetaWaylandPointerClass *klass) + { ++ GObjectClass *object_class = G_OBJECT_CLASS (klass); ++ ++ object_class->finalize = meta_wayland_pointer_finalize; ++ + signals[FOCUS_SURFACE_CHANGED] = g_signal_new ("focus-surface-changed", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, +diff --git a/src/wayland/meta-wayland-seat.c b/src/wayland/meta-wayland-seat.c +index 10dbc4e..3d35f67 100644 +--- a/src/wayland/meta-wayland-seat.c ++++ b/src/wayland/meta-wayland-seat.c +@@ -46,8 +46,7 @@ seat_get_pointer (struct wl_client *client, + MetaWaylandSeat *seat = wl_resource_get_user_data (resource); + MetaWaylandPointer *pointer = seat->pointer; + +- if (meta_wayland_seat_has_pointer (seat)) +- meta_wayland_pointer_create_new_resource (pointer, client, resource, id); ++ meta_wayland_pointer_create_new_resource (pointer, client, resource, id); + } + + static void +@@ -58,8 +57,7 @@ seat_get_keyboard (struct wl_client *client, + MetaWaylandSeat *seat = wl_resource_get_user_data (resource); + MetaWaylandKeyboard *keyboard = seat->keyboard; + +- if (meta_wayland_seat_has_keyboard (seat)) +- meta_wayland_keyboard_create_new_resource (keyboard, client, resource, id); ++ meta_wayland_keyboard_create_new_resource (keyboard, client, resource, id); + } + + static void +@@ -70,8 +68,7 @@ seat_get_touch (struct wl_client *client, + MetaWaylandSeat *seat = wl_resource_get_user_data (resource); + MetaWaylandTouch *touch = seat->touch; + +- if (meta_wayland_seat_has_touch (seat)) +- meta_wayland_touch_create_new_resource (touch, client, resource, id); ++ meta_wayland_touch_create_new_resource (touch, client, resource, id); + } + + static void +diff --git a/src/wayland/meta-wayland-touch.c b/src/wayland/meta-wayland-touch.c +index 9c2cfc9..795380f 100644 +--- a/src/wayland/meta-wayland-touch.c ++++ b/src/wayland/meta-wayland-touch.c +@@ -602,16 +602,8 @@ meta_wayland_touch_create_new_resource (MetaWaylandTouch *touch, + struct wl_resource *seat_resource, + uint32_t id) + { +- MetaWaylandSeat *seat = wl_resource_get_user_data (seat_resource); + struct wl_resource *cr; + +- if (!meta_wayland_seat_has_touch (seat)) +- { +- wl_resource_post_error (seat_resource, WL_DISPLAY_ERROR_INVALID_METHOD, +- "Cannot retrieve touch interface without touch capability"); +- return; +- } +- + cr = wl_resource_create (client, &wl_touch_interface, wl_resource_get_version (seat_resource), id); + wl_resource_set_implementation (cr, &touch_interface, touch, unbind_resource); + wl_list_insert (&touch->resource_list, wl_resource_get_link (cr)); diff -Nru mutter-3.36.1/debian/patches/series mutter-3.36.9/debian/patches/series --- mutter-3.36.1/debian/patches/series 2020-04-16 20:04:59.000000000 +0000 +++ mutter-3.36.9/debian/patches/series 2021-11-03 19:10:34.000000000 +0000 @@ -1,23 +1,8 @@ -clutter-actor-Fix-pick-when-actor-is-not-allocated.patch -tests-actor-pick-Remove-tabs.patch -tests-actor-pick-Allocate-actor-before-picking.patch -clutter-click-action-Do-not-process-captured-event-if-act.patch -clutter-stage-Add-API-to-get_next_presentation_time.patch -clutter-master-clock-default-Sync-timelines-to-hardware-v.patch -cogl-Don-t-allow-creating-sized-textures-with-0-pixels.patch -cogl-Defend-against-empty-or-unallocated-framebuffers.patch -window-actor-Set-viewport-when-blitting-to-screencast-fb.patch -Update-Slovak-translation.patch -x11-fix-compilation-if-libwacom-false.patch -window-Check-aliveness-a-bit-less-aggressively.patch -clutter-stage-Don-t-assume-stage-relayouts-reallocate-eve.patch -backends-x11-Fix-access-to-WacomDevice.patch -backends-native-Translate-coordinates-of-absolute-motion-.patch -wayland-xdnd-Add-error-traps-around-Xdnd-IPC.patch -monitor-config-manager-Fallback-to-closed-laptop-lid-conf.patch +clutter-backend-x11-Don-t-set-the-font-dpi-computed-on-X1.patch theme-use-gtk_render_icon_suface-to-paint-button-icon.patch theme-load-icons-as-Gtk-does-with-fallback-and-RTL-suppor.patch meson-add-back-default_driver-option.patch +mutter-wayland-seat-race-fix.patch x11-Add-support-for-fractional-scaling-using-Randr.patch debian/synaptics-support.patch debian/tests-Tag-closed-transient-no-input-tests-as-flaky.patch diff -Nru mutter-3.36.1/debian/patches/tests-actor-pick-Allocate-actor-before-picking.patch mutter-3.36.9/debian/patches/tests-actor-pick-Allocate-actor-before-picking.patch --- mutter-3.36.1/debian/patches/tests-actor-pick-Allocate-actor-before-picking.patch 2020-04-16 20:04:59.000000000 +0000 +++ mutter-3.36.9/debian/patches/tests-actor-pick-Allocate-actor-before-picking.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,44 +0,0 @@ -From: Georges Basile Stavracas Neto -Date: Tue, 31 Mar 2020 22:01:53 +0000 -Subject: tests/actor-pick: Allocate actor before picking - -Picking now only happens on allocated actors, but the -callback in the actor-pick test is not waiting for the -stage to run an allocation cycle. Ideally, we'd wait -for this cycle, but for now, forcing an allocation works -as well. - -Allocate the overlay actor in the actor-pick test. - -Forwarded: https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1169 -Applied-upstream: 3.36.2, commit:6f9b5edd4deeb412e644122ce2f15b3d593bd07a ---- - src/tests/clutter/conform/actor-pick.c | 8 ++++++++ - 1 file changed, 8 insertions(+) - -diff --git a/src/tests/clutter/conform/actor-pick.c b/src/tests/clutter/conform/actor-pick.c -index 53ac8ec..dcee964 100644 ---- a/src/tests/clutter/conform/actor-pick.c -+++ b/src/tests/clutter/conform/actor-pick.c -@@ -67,6 +67,9 @@ on_timeout (gpointer data) - } - else if (test_num == 2) - { -+ ClutterActorBox over_actor_box = -+ CLUTTER_ACTOR_BOX_INIT (0, 0, STAGE_WIDTH, STAGE_HEIGHT); -+ - /* Make the actor visible but set a clip so that only some - of the actors are accessible */ - clutter_actor_show (over_actor); -@@ -76,6 +79,11 @@ on_timeout (gpointer data) - state->actor_width * (ACTORS_X - 4), - state->actor_height * (ACTORS_Y - 4)); - -+ /* Only allocated actors can be picked, so force an allocation -+ * of the overlay actor here. -+ */ -+ clutter_actor_allocate (over_actor, &over_actor_box, 0); -+ - if (g_test_verbose ()) - g_print ("Clipped covering actor:\n"); - } diff -Nru mutter-3.36.1/debian/patches/tests-actor-pick-Remove-tabs.patch mutter-3.36.9/debian/patches/tests-actor-pick-Remove-tabs.patch --- mutter-3.36.1/debian/patches/tests-actor-pick-Remove-tabs.patch 2020-04-16 20:04:59.000000000 +0000 +++ mutter-3.36.9/debian/patches/tests-actor-pick-Remove-tabs.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,43 +0,0 @@ -From: Georges Basile Stavracas Neto -Date: Tue, 31 Mar 2020 21:58:44 +0000 -Subject: tests/actor-pick: Remove tabs - -They're evil. - -Forwarded: https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1169 -Applied-upstream: 3.36.2, commit:31809e121424ec6609e947ab2d6bde6ae792b539 ---- - src/tests/clutter/conform/actor-pick.c | 12 ++++++------ - 1 file changed, 6 insertions(+), 6 deletions(-) - -diff --git a/src/tests/clutter/conform/actor-pick.c b/src/tests/clutter/conform/actor-pick.c -index 09c5bf7..53ac8ec 100644 ---- a/src/tests/clutter/conform/actor-pick.c -+++ b/src/tests/clutter/conform/actor-pick.c -@@ -175,10 +175,10 @@ actor_pick (void) - for (y = 0; y < ACTORS_Y; y++) - for (x = 0; x < ACTORS_X; x++) - { -- ClutterColor color = { x * 255 / (ACTORS_X - 1), -- y * 255 / (ACTORS_Y - 1), -- 128, 255 }; -- ClutterActor *rect = clutter_rectangle_new_with_color (&color); -+ ClutterColor color = { x * 255 / (ACTORS_X - 1), -+ y * 255 / (ACTORS_Y - 1), -+ 128, 255 }; -+ ClutterActor *rect = clutter_rectangle_new_with_color (&color); - - clutter_actor_set_position (rect, - x * state.actor_width, -@@ -187,9 +187,9 @@ actor_pick (void) - state.actor_width, - state.actor_height); - -- clutter_actor_add_child (state.stage, rect); -+ clutter_actor_add_child (state.stage, rect); - -- state.actors[y * ACTORS_X + x] = rect; -+ state.actors[y * ACTORS_X + x] = rect; - } - - clutter_actor_show (state.stage); diff -Nru mutter-3.36.1/debian/patches/Update-Slovak-translation.patch mutter-3.36.9/debian/patches/Update-Slovak-translation.patch --- mutter-3.36.1/debian/patches/Update-Slovak-translation.patch 2020-04-16 20:04:59.000000000 +0000 +++ mutter-3.36.9/debian/patches/Update-Slovak-translation.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,348 +0,0 @@ -From: =?utf-8?q?Du=C5=A1an_Kazik?= -Date: Sun, 5 Apr 2020 20:22:08 +0000 -Subject: Update Slovak translation - -Origin: upstream, 3.36.2, commit:b0709504ea22cdbd51225f9c0bf497d12351b37f ---- - po/sk.po | 167 +++++++++++++++++++++++++++++++++++++++++---------------------- - 1 file changed, 108 insertions(+), 59 deletions(-) - -diff --git a/po/sk.po b/po/sk.po -index 89e6859..d22e1a2 100644 ---- a/po/sk.po -+++ b/po/sk.po -@@ -13,8 +13,8 @@ msgid "" - msgstr "" - "Project-Id-Version: mutter\n" - "Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/mutter/issues\n" --"POT-Creation-Date: 2018-02-06 04:14+0000\n" --"PO-Revision-Date: 2018-03-17 21:52+0100\n" -+"POT-Creation-Date: 2020-03-30 20:11+0000\n" -+"PO-Revision-Date: 2020-04-05 22:21+0200\n" - "Last-Translator: Dušan Kazik \n" - "Language-Team: Slovak \n" - "Language: sk\n" -@@ -22,7 +22,7 @@ msgstr "" - "Content-Type: text/plain; charset=UTF-8\n" - "Content-Transfer-Encoding: 8bit\n" - "Plural-Forms: nplurals=3; plural=(n==1) ? 1 : (n>=2 && n<=4) ? 2 : 0;\n" --"X-Generator: Poedit 2.0.6\n" -+"X-Generator: Poedit 2.3\n" - - #: data/50-mutter-navigation.xml:6 - msgid "Navigation" -@@ -468,29 +468,47 @@ msgid "" - "proof. Currently possible keywords: • “scale-monitor-framebuffer” — makes " - "mutter default to layout logical monitors in a logical pixel coordinate " - "space, while scaling monitor framebuffers instead of window content, to " --"manage HiDPI monitors. Does not require a restart. • “remote-desktop” — " --"enables remote desktop support. To support remote desktop with screen " --"sharing, “screen-cast” must also be enabled. • “screen-cast” — enables " --"screen cast support." -+"manage HiDPI monitors. Does not require a restart. • “rt-scheduler” — makes " -+"mutter request a low priority real-time scheduling. The executable or user " -+"must have CAP_SYS_NICE. Requires a restart. • “autostart-xwayland” — " -+"initializes Xwayland lazily if there are X11 clients. Requires restart." -+msgstr "" -+ -+#: data/org.gnome.mutter.gschema.xml.in:134 -+msgid "Modifier to use to locate the pointer" -+msgstr "Modifikátor použitý na lokalizovanie ukazovateľa" -+ -+#: data/org.gnome.mutter.gschema.xml.in:135 -+msgid "This key will initiate the “locate pointer” action." -+msgstr "" -+ -+#: data/org.gnome.mutter.gschema.xml.in:142 -+msgid "Timeout for check-alive ping" -+msgstr "" -+ -+#: data/org.gnome.mutter.gschema.xml.in:143 -+msgid "" -+"Number of milliseconds a client has to respond to a ping request in order to " -+"not be detected as frozen. Using 0 will disable the alive check completely." - msgstr "" - - # summary --#: data/org.gnome.mutter.gschema.xml.in:145 -+#: data/org.gnome.mutter.gschema.xml.in:165 - msgid "Select window from tab popup" - msgstr "Vybrať okno z rozbaľovacej ponuky tabulátora" - - # summary --#: data/org.gnome.mutter.gschema.xml.in:150 -+#: data/org.gnome.mutter.gschema.xml.in:170 - msgid "Cancel tab popup" - msgstr "Zrušit rozbaľovaciu ponuku tabulátora" - - # PK: predpokladam ze to prepisane medzi tlacidlami - # description --#: data/org.gnome.mutter.gschema.xml.in:155 -+#: data/org.gnome.mutter.gschema.xml.in:175 - msgid "Switch monitor configurations" - msgstr "Prepnúť nastavenia monitorov" - --#: data/org.gnome.mutter.gschema.xml.in:160 -+#: data/org.gnome.mutter.gschema.xml.in:180 - msgid "Rotates the built-in monitor configuration" - msgstr "Otočí nastavenie vstavaného monitora" - -@@ -554,23 +572,27 @@ msgid "Re-enable shortcuts" - msgstr "Znovu povoliť klávesové skratky" - - #: data/org.gnome.mutter.wayland.gschema.xml.in:64 --msgid "Allow grabs with Xwayland" -+msgid "Allow X11 grabs to lock keyboard focus with Xwayland" - msgstr "" - - #: data/org.gnome.mutter.wayland.gschema.xml.in:65 - msgid "" --"Allow keyboard grabs issued by X11 applications running in Xwayland to be " --"taken into account. For a X11 grab to be taken into account under Wayland, " --"the client must also either send a specific X11 ClientMessage to the root " --"window or be among the applications white-listed in key “xwayland-grab-" --"access-rules”." -+"Allow all keyboard events to be routed to X11 “override redirect” windows " -+"with a grab when running in Xwayland. This option is to support X11 clients " -+"which map an “override redirect” window (which do not receive keyboard " -+"focus) and issue a keyboard grab to force all keyboard events to that " -+"window. This option is seldom used and has no effect on regular X11 windows " -+"which can receive keyboard focus under normal circumstances. For a X11 grab " -+"to be taken into account under Wayland, the client must also either send a " -+"specific X11 ClientMessage to the root window or be among the applications " -+"white-listed in key “xwayland-grab-access-rules”." - msgstr "" - --#: data/org.gnome.mutter.wayland.gschema.xml.in:77 -+#: data/org.gnome.mutter.wayland.gschema.xml.in:84 - msgid "Xwayland applications allowed to issue keyboard grabs" - msgstr "" - --#: data/org.gnome.mutter.wayland.gschema.xml.in:78 -+#: data/org.gnome.mutter.wayland.gschema.xml.in:85 - msgid "" - "List the resource names or resource class of X11 windows either allowed or " - "not allowed to issue X11 keyboard grabs under Xwayland. The resource name or " -@@ -587,7 +609,7 @@ msgstr "" - #. TRANSLATORS: This string refers to a button that switches between - #. * different modes. - #. --#: src/backends/meta-input-settings.c:2260 -+#: src/backends/meta-input-settings.c:2631 - #, c-format - msgid "Mode Switch (Group %d)" - msgstr "Prepínač režimu (skupina č. %d)" -@@ -597,53 +619,61 @@ msgstr "Prepínač režimu (skupina č. %d)" - #. TRANSLATORS: This string refers to an action, cycles drawing tablets' - #. * mapping through the available outputs. - #. --#: src/backends/meta-input-settings.c:2283 -+#: src/backends/meta-input-settings.c:2654 - msgid "Switch monitor" - msgstr "Prepnúť monitor" - --#: src/backends/meta-input-settings.c:2285 -+#: src/backends/meta-input-settings.c:2656 - msgid "Show on-screen help" - msgstr "Zobraziť pomocníka na obrazovke" - --#: src/backends/meta-monitor-manager.c:900 -+#: src/backends/meta-monitor.c:226 - msgid "Built-in display" - msgstr "Vstavaný displej" - --#: src/backends/meta-monitor-manager.c:923 -+#: src/backends/meta-monitor.c:255 - msgid "Unknown" - msgstr "Neznámy" - --#: src/backends/meta-monitor-manager.c:925 -+#: src/backends/meta-monitor.c:257 - msgid "Unknown Display" - msgstr "Neznámy displej" - --#. TRANSLATORS: this is a monitor vendor name, followed by a --#. * size in inches, like 'Dell 15"' --#. --#: src/backends/meta-monitor-manager.c:933 -+#: src/backends/meta-monitor.c:265 - #, c-format -+#| msgid "%s %s" -+msgctxt "" -+"This is a monitor vendor name, followed by a size in inches, like 'Dell 15\"'" - msgid "%s %s" - msgstr "%s %s" - -+#: src/backends/meta-monitor.c:273 -+#, c-format -+#| msgid "%s %s" -+msgctxt "" -+"This is a monitor vendor name followed by product/model name where size in " -+"inches could not be calculated, e.g. Dell U2414H" -+msgid "%s %s" -+msgstr "%s %s" -+ -+#. Translators: this string will appear in Sysprof -+#: src/backends/meta-profiler.c:79 -+msgid "Compositor" -+msgstr "Kompozítor" -+ - #. This probably means that a non-WM compositor like xcompmgr is running; - #. * we have no way to get it to exit --#: src/compositor/compositor.c:481 -+#: src/compositor/compositor.c:533 - #, c-format - msgid "" - "Another compositing manager is already running on screen %i on display “%s”." - msgstr "" - "Pre obrazovku č. %i na displeji „%s“ je spustený už iný správca rozloženia." - --#: src/core/bell.c:194 -+#: src/core/bell.c:192 - msgid "Bell event" - msgstr "Udalosť zvončeka" - --# X window system preloz, napr. system na spravu okien X --#: src/core/display.c:608 --#, c-format --msgid "Failed to open X Window System display “%s”\n" --msgstr "Zlyhalo otvorenie displeja systému na správu okien X „%s“\n" -- - # cmd desc - #: src/core/main.c:190 - msgid "Disable connection to session manager" -@@ -683,41 +713,45 @@ msgstr "Spustí ako kompozitor protokolu wayland" - msgid "Run as a nested compositor" - msgstr "Spustí ako kompozitor s vnoreným režimom" - --#: src/core/main.c:240 -+#: src/core/main.c:238 -+msgid "Run wayland compositor without starting Xwayland" -+msgstr "" -+ -+#: src/core/main.c:246 - msgid "Run as a full display server, rather than nested" - msgstr "Spustí ako plnohodnotný zobrazovací server, namiesto vnoreného režimu" - --#: src/core/main.c:246 -+#: src/core/main.c:252 - msgid "Run with X11 backend" - msgstr "Spustí s obslužným programom X11" - - # %s is a window title - #. Translators: %s is a window title --#: src/core/meta-close-dialog-default.c:147 -+#: src/core/meta-close-dialog-default.c:151 - #, c-format - msgid "“%s” is not responding." - msgstr "„%s“ neodpovedá." - --#: src/core/meta-close-dialog-default.c:149 -+#: src/core/meta-close-dialog-default.c:153 - msgid "Application is not responding." - msgstr "Aplikácia neodpovedá." - --#: src/core/meta-close-dialog-default.c:154 -+#: src/core/meta-close-dialog-default.c:158 - msgid "" - "You may choose to wait a short while for it to continue or force the " - "application to quit entirely." - msgstr "" - "Môžete chvíľu počkať na pokračovanie aplikácie, alebo ju môžete ukončiť." - --#: src/core/meta-close-dialog-default.c:161 -+#: src/core/meta-close-dialog-default.c:165 - msgid "_Force Quit" - msgstr "_Vynútiť ukončenie" - --#: src/core/meta-close-dialog-default.c:161 -+#: src/core/meta-close-dialog-default.c:165 - msgid "_Wait" - msgstr "_Počkať" - --#: src/core/mutter.c:39 -+#: src/core/mutter.c:38 - #, c-format - msgid "" - "mutter %s\n" -@@ -733,21 +767,30 @@ msgstr "" - "Záruka sa NEPOSKYTUJE; ani na PREDAJNOSŤ alebo VHODNOSŤ PRE URČITÝ ÚČEL.\n" - - # cmd desc --#: src/core/mutter.c:53 -+#: src/core/mutter.c:52 - msgid "Print version" - msgstr "Zobrazí verziu" - - # cmd desc --#: src/core/mutter.c:59 -+#: src/core/mutter.c:58 - msgid "Mutter plugin to use" - msgstr "Použije zásuvný modul Mutter" - --#: src/core/prefs.c:1997 -+#: src/core/prefs.c:1911 - #, c-format - msgid "Workspace %d" - msgstr "Pracovný priestor č. %d" - --#: src/core/screen.c:583 -+#: src/core/util.c:122 -+msgid "Mutter was compiled without support for verbose mode\n" -+msgstr "Mutter bol skompilovaný bez výpisu podrobností pri behu\n" -+ -+#: src/wayland/meta-wayland-tablet-pad.c:568 -+#, c-format -+msgid "Mode Switch: Mode %d" -+msgstr "Prepínač režimu: Režim č. %d" -+ -+#: src/x11/meta-x11-display.c:676 - #, c-format - msgid "" - "Display “%s” already has a window manager; try using the --replace option to " -@@ -756,21 +799,27 @@ msgstr "" - "Displej „%s“ už má správcu okien. Skúste použiť prepínač --replace, aby sa " - "aktuálny správca nahradil." - --#: src/core/screen.c:668 -+#: src/x11/meta-x11-display.c:1089 -+msgid "Failed to initialize GDK\n" -+msgstr "Zlyhala inicializácia GDK\n" -+ -+# X window system preloz, napr. system na spravu okien X -+#: src/x11/meta-x11-display.c:1113 -+#, c-format -+msgid "Failed to open X Window System display “%s”\n" -+msgstr "Zlyhalo otvorenie displeja systému na správu okien X „%s“\n" -+ -+#: src/x11/meta-x11-display.c:1196 - #, c-format - msgid "Screen %d on display “%s” is invalid\n" - msgstr "Obrazovka č. %d na displeji „%s“ nie je platná\n" - --#: src/core/util.c:120 --msgid "Mutter was compiled without support for verbose mode\n" --msgstr "Mutter bol skompilovaný bez výpisu podrobností pri behu\n" -- --#: src/wayland/meta-wayland-tablet-pad.c:563 -+#: src/x11/meta-x11-selection-input-stream.c:460 - #, c-format --msgid "Mode Switch: Mode %d" --msgstr "Prepínač režimu: Režim č. %d" -+msgid "Format %s not supported" -+msgstr "Formát %s nie je podporovaný" - --#: src/x11/session.c:1818 -+#: src/x11/session.c:1821 - msgid "" - "These windows do not support “save current setup” and will have to be " - "restarted manually next time you log in." -@@ -779,7 +828,7 @@ msgstr "" - "prihlásení ich budete musieť znovu spustiť ručne." - - # window title; wm_client_machine --#: src/x11/window-props.c:559 -+#: src/x11/window-props.c:569 - #, c-format - msgid "%s (on %s)" - msgstr "%s (na %s)" diff -Nru mutter-3.36.1/debian/patches/wayland-xdnd-Add-error-traps-around-Xdnd-IPC.patch mutter-3.36.9/debian/patches/wayland-xdnd-Add-error-traps-around-Xdnd-IPC.patch --- mutter-3.36.1/debian/patches/wayland-xdnd-Add-error-traps-around-Xdnd-IPC.patch 2020-04-16 20:04:59.000000000 +0000 +++ mutter-3.36.9/debian/patches/wayland-xdnd-Add-error-traps-around-Xdnd-IPC.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,105 +0,0 @@ -From: Carlos Garnacho -Date: Tue, 7 Apr 2020 19:16:16 +0200 -Subject: wayland/xdnd: Add error traps around Xdnd* IPC - -Make all of them spew criticals, except for XdndLeave as it's feasible -to expect the window we are sending the event to did disappear in the -way (eg. if the window is destroyed while the DnD operation is ongoing -and the pointer is over the window). - -Bug: https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/2590 -Forwarded: https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1184 -Origin: upstream, 3.36.2 ---- - src/wayland/meta-xwayland-dnd.c | 24 ++++++++++++++++++++++++ - 1 file changed, 24 insertions(+) - -diff --git a/src/wayland/meta-xwayland-dnd.c b/src/wayland/meta-xwayland-dnd.c -index 6b75362..ea81d71 100644 ---- a/src/wayland/meta-xwayland-dnd.c -+++ b/src/wayland/meta-xwayland-dnd.c -@@ -145,6 +145,8 @@ xdnd_send_enter (MetaXWaylandDnd *dnd, - gchar **p; - struct wl_array *source_mime_types; - -+ meta_x11_error_trap_push (x11_display); -+ - data_source = compositor->seat->data_device.dnd_data_source; - xev.xclient.type = ClientMessage; - xev.xclient.message_type = xdnd_atoms[ATOM_DND_ENTER]; -@@ -189,6 +191,9 @@ xdnd_send_enter (MetaXWaylandDnd *dnd, - } - - XSendEvent (xdisplay, dest, False, NoEventMask, &xev); -+ -+ if (meta_x11_error_trap_pop_with_return (x11_display) != Success) -+ g_critical ("Error sending XdndEnter"); - } - - static void -@@ -205,7 +210,9 @@ xdnd_send_leave (MetaXWaylandDnd *dnd, - xev.xclient.window = dest; - xev.xclient.data.l[0] = x11_display->selection.xwindow; - -+ meta_x11_error_trap_push (x11_display); - XSendEvent (xdisplay, dest, False, NoEventMask, &xev); -+ meta_x11_error_trap_pop (x11_display); - } - - static void -@@ -241,7 +248,11 @@ xdnd_send_position (MetaXWaylandDnd *dnd, - xev.xclient.data.l[3] = time; - xev.xclient.data.l[4] = action_to_atom (action); - -+ meta_x11_error_trap_push (x11_display); - XSendEvent (xdisplay, dest, False, NoEventMask, &xev); -+ -+ if (meta_x11_error_trap_pop_with_return (x11_display) != Success) -+ g_critical ("Error sending XdndPosition"); - } - - static void -@@ -261,7 +272,11 @@ xdnd_send_drop (MetaXWaylandDnd *dnd, - xev.xclient.data.l[0] = x11_display->selection.xwindow; - xev.xclient.data.l[2] = time; - -+ meta_x11_error_trap_push (x11_display); - XSendEvent (xdisplay, dest, False, NoEventMask, &xev); -+ -+ if (meta_x11_error_trap_pop_with_return (x11_display) != Success) -+ g_critical ("Error sending XdndDrop"); - } - - static void -@@ -289,7 +304,11 @@ xdnd_send_finished (MetaXWaylandDnd *dnd, - xev.xclient.data.l[2] = action_to_atom (action); - } - -+ meta_x11_error_trap_push (x11_display); - XSendEvent (xdisplay, dest, False, NoEventMask, &xev); -+ -+ if (meta_x11_error_trap_pop_with_return (x11_display) != Success) -+ g_critical ("Error sending XdndFinished"); - } - - static void -@@ -297,6 +316,7 @@ xdnd_send_status (MetaXWaylandDnd *dnd, - Window dest, - uint32_t action) - { -+ MetaX11Display *x11_display = meta_get_display ()->x11_display; - Display *xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()); - XEvent xev = { 0 }; - -@@ -312,7 +332,11 @@ xdnd_send_status (MetaXWaylandDnd *dnd, - if (xev.xclient.data.l[4]) - xev.xclient.data.l[1] |= 1 << 0; /* Bit 1: dest accepts the drop */ - -+ meta_x11_error_trap_push (x11_display); - XSendEvent (xdisplay, dest, False, NoEventMask, &xev); -+ -+ if (meta_x11_error_trap_pop_with_return (x11_display) != Success) -+ g_critical ("Error sending Xdndstatus"); - } - - static void diff -Nru mutter-3.36.1/debian/patches/window-actor-Set-viewport-when-blitting-to-screencast-fb.patch mutter-3.36.9/debian/patches/window-actor-Set-viewport-when-blitting-to-screencast-fb.patch --- mutter-3.36.1/debian/patches/window-actor-Set-viewport-when-blitting-to-screencast-fb.patch 2020-04-16 20:04:59.000000000 +0000 +++ mutter-3.36.9/debian/patches/window-actor-Set-viewport-when-blitting-to-screencast-fb.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,29 +0,0 @@ -From: =?utf-8?q?Jonas_=C3=85dahl?= -Date: Fri, 3 Apr 2020 15:12:58 +0000 -Subject: window-actor: Set viewport when blitting to screencast fb - -This fixes an issue where a non-maximized screen casted window would be -stretched to fill the whole screen cast stream, instead of just the crop -that corresponds to the current window size. - -https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1174 - -(cherry picked from commit a6f94696e2e8ade9e800f3b37092a5f40e22cf38) - -Origin: upstream, 3.36.2, commit:7e94311e2eb78c5fbaf8df047bebc92bd501aeb8 ---- - src/compositor/meta-window-actor.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/src/compositor/meta-window-actor.c b/src/compositor/meta-window-actor.c -index 92355a9..31e0cb6 100644 ---- a/src/compositor/meta-window-actor.c -+++ b/src/compositor/meta-window-actor.c -@@ -1300,6 +1300,7 @@ meta_window_actor_blit_to_framebuffer (MetaScreenCastWindow *screen_cast_window, - cogl_color_init_from_4ub (&clear_color, 0, 0, 0, 0); - cogl_framebuffer_clear (framebuffer, COGL_BUFFER_BIT_COLOR, &clear_color); - cogl_framebuffer_orthographic (framebuffer, 0, 0, width, height, 0, 1.0); -+ cogl_framebuffer_set_viewport (framebuffer, 0, 0, width, height); - - meta_rectangle_scale_double (bounds, resource_scale, - META_ROUNDING_STRATEGY_GROW, diff -Nru mutter-3.36.1/debian/patches/window-Check-aliveness-a-bit-less-aggressively.patch mutter-3.36.9/debian/patches/window-Check-aliveness-a-bit-less-aggressively.patch --- mutter-3.36.1/debian/patches/window-Check-aliveness-a-bit-less-aggressively.patch 2020-04-16 20:04:59.000000000 +0000 +++ mutter-3.36.9/debian/patches/window-Check-aliveness-a-bit-less-aggressively.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,70 +0,0 @@ -From: =?utf-8?q?Jonas_=C3=85dahl?= -Date: Tue, 7 Apr 2020 08:39:10 +0000 -Subject: window: Check aliveness a bit less aggressively - -Currently we check whether a window is alive everytime it's focused. -This means that an application that doesn't respond to the check-alive -event during startup always showing the "application froze" dialog, -without the user ever trying to interact with it. - -An example where this tends to to happen is with games, and for this -particular scenario, it's purely an annoyance, as I never tried to -interact with the game window in the first place, so I don't care that -it's not responding - it's loading. - -To avoid these unnecessary particular "app-is-frozen" popups, remove the -alive check from the focus function, and instead move it back to the -"meta_window_activate_full()" call. To also trigger it slightly more -often, also add it to the path that triggers the window focus when a -user actively clicks on the window. - -This means that we currently check whether a window is alive on: - - * Any time the window is activated. This means e.g. alt-tab or - selecting the window in the overview. - * The user clicks on the window. - -Note that the second only works for an already focused window on -Wayland, as on X11, we don't refocus it. This particular case isn't -changed with this commit, as we didn't call meta_window_focus() to begin -with here. - -https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1182 - -(cherry picked from commit 8df3b21a51b0e8dcea4a4376426880e4f3c4f837) - -Origin: upstream, 3.36.2 ---- - src/core/window.c | 5 +++-- - 1 file changed, 3 insertions(+), 2 deletions(-) - -diff --git a/src/core/window.c b/src/core/window.c -index 3356fc7..ea721f7 100644 ---- a/src/core/window.c -+++ b/src/core/window.c -@@ -3751,6 +3751,8 @@ meta_window_activate_full (MetaWindow *window, - meta_window_focus (window, timestamp); - else - meta_workspace_activate_with_focus (window->workspace, window, timestamp); -+ -+ meta_window_check_alive (window, timestamp); - } - - /* This function exists since most of the functionality in window_activate -@@ -4790,8 +4792,6 @@ meta_window_focus (MetaWindow *window, - return; - } - -- meta_window_check_alive (window, timestamp); -- - META_WINDOW_GET_CLASS (window)->focus (window, timestamp); - - if (window->display->event_route == META_EVENT_ROUTE_NORMAL) -@@ -8349,6 +8349,7 @@ meta_window_handle_ungrabbed_event (MetaWindow *window, - "Focusing %s due to button %u press (display.c)\n", - window->desc, button); - meta_window_focus (window, event->any.time); -+ meta_window_check_alive (window, event->any.time); - } - else - /* However, do allow terminals to lose focus due to new diff -Nru mutter-3.36.1/debian/patches/x11-Add-support-for-fractional-scaling-using-Randr.patch mutter-3.36.9/debian/patches/x11-Add-support-for-fractional-scaling-using-Randr.patch --- mutter-3.36.1/debian/patches/x11-Add-support-for-fractional-scaling-using-Randr.patch 2020-04-16 20:04:59.000000000 +0000 +++ mutter-3.36.9/debian/patches/x11-Add-support-for-fractional-scaling-using-Randr.patch 2021-11-03 19:10:34.000000000 +0000 @@ -8,40 +8,37 @@ Bug-Ubuntu: https://bugs.launchpad.net/ubuntu/+source/mutter/+bug/1820850 Forwarded: No, forwarding is in progress and planned though --- - data/meson.build | 7 + - data/org.gnome.mutter.gschema.xml.in | 4 + - data/org.gnome.mutter.x11.gschema.xml.in | 30 ++ - src/backends/meta-crtc.h | 1 + - src/backends/meta-monitor-config-manager.c | 141 +++++- - src/backends/meta-monitor-config-migration.c | 15 +- - src/backends/meta-monitor-config-store.c | 1 + - src/backends/meta-monitor-manager-dummy.c | 24 +- - src/backends/meta-monitor-manager-private.h | 34 +- - src/backends/meta-monitor-manager.c | 362 +++++++++++++-- - src/backends/meta-monitor.c | 60 ++- - src/backends/meta-monitor.h | 6 +- - src/backends/meta-settings-private.h | 9 + - src/backends/meta-settings.c | 76 +++- - src/backends/native/meta-monitor-manager-kms.c | 44 +- - src/backends/x11/meta-crtc-xrandr.c | 88 +++- - src/backends/x11/meta-crtc-xrandr.h | 13 +- - src/backends/x11/meta-gpu-xrandr.c | 89 +++- - src/backends/x11/meta-gpu-xrandr.h | 4 + - src/backends/x11/meta-monitor-manager-xrandr.c | 503 +++++++++++++++------ - src/backends/x11/meta-monitor-manager-xrandr.h | 4 +- - src/backends/x11/meta-output-xrandr.c | 5 +- - src/compositor/meta-compositor-x11.c | 98 +++- - src/core/boxes-private.h | 4 + - src/core/boxes.c | 21 + - .../meta-selection-source-memory-pool-private.h | 47 ++ - src/core/meta-selection-source-memory-pool.c | 195 ++++++++ - src/core/window.c | 19 + - src/org.gnome.Mutter.DisplayConfig.xml | 5 + - src/tests/meta-monitor-manager-test.c | 13 +- - 30 files changed, 1652 insertions(+), 270 deletions(-) + data/meson.build | 7 + + data/org.gnome.mutter.gschema.xml.in | 4 + + data/org.gnome.mutter.x11.gschema.xml.in | 30 ++ + src/backends/meta-crtc.h | 1 + + src/backends/meta-monitor-config-manager.c | 180 +++++++- + src/backends/meta-monitor-config-manager.h | 5 + + src/backends/meta-monitor-config-migration.c | 15 +- + src/backends/meta-monitor-config-store.c | 17 + + src/backends/meta-monitor-manager-dummy.c | 24 +- + src/backends/meta-monitor-manager-private.h | 34 +- + src/backends/meta-monitor-manager.c | 505 ++++++++++++++++++++-- + src/backends/meta-monitor.c | 60 ++- + src/backends/meta-monitor.h | 6 +- + src/backends/meta-settings-private.h | 13 + + src/backends/meta-settings.c | 148 ++++++- + src/backends/native/meta-monitor-manager-kms.c | 44 +- + src/backends/x11/meta-crtc-xrandr.c | 92 +++- + src/backends/x11/meta-crtc-xrandr.h | 14 +- + src/backends/x11/meta-gpu-xrandr.c | 106 ++++- + src/backends/x11/meta-gpu-xrandr.h | 4 + + src/backends/x11/meta-monitor-manager-xrandr.c | 571 +++++++++++++++++++------ + src/backends/x11/meta-monitor-manager-xrandr.h | 4 +- + src/backends/x11/meta-output-xrandr.c | 5 +- + src/compositor/meta-compositor-x11.c | 99 ++++- + src/core/boxes-private.h | 4 + + src/core/boxes.c | 21 + + src/core/window.c | 19 + + src/org.gnome.Mutter.DisplayConfig.xml | 5 + + src/tests/meta-monitor-manager-test.c | 13 +- + 29 files changed, 1779 insertions(+), 271 deletions(-) create mode 100644 data/org.gnome.mutter.x11.gschema.xml.in - create mode 100644 src/core/meta-selection-source-memory-pool-private.h - create mode 100644 src/core/meta-selection-source-memory-pool.c diff --git a/data/meson.build b/data/meson.build index 3ac94cf..730258b 100644 @@ -125,12 +122,12 @@ MetaCrtcConfig *config; diff --git a/src/backends/meta-monitor-config-manager.c b/src/backends/meta-monitor-config-manager.c -index 6e31432..b70f2eb 100644 +index 6a7c807..d8646fa 100644 --- a/src/backends/meta-monitor-config-manager.c +++ b/src/backends/meta-monitor-config-manager.c -@@ -205,6 +205,18 @@ assign_monitor_crtc (MetaMonitor *monitor, - crtc_transform)) - crtc_transform = META_MONITOR_TRANSFORM_NORMAL; +@@ -208,6 +208,18 @@ assign_monitor_crtc (MetaMonitor *monitor, + else + crtc_hw_transform = META_MONITOR_TRANSFORM_NORMAL; + scale = data->logical_monitor_config->scale; + if (!meta_monitor_manager_is_scale_supported (data->monitor_manager, @@ -147,15 +144,24 @@ meta_monitor_calculate_crtc_pos (monitor, mode, output, crtc_transform, &crtc_x, &crtc_y); -@@ -244,6 +256,7 @@ assign_monitor_crtc (MetaMonitor *monitor, - .crtc = crtc, +@@ -222,6 +234,8 @@ assign_monitor_crtc (MetaMonitor *monitor, + case META_LOGICAL_MONITOR_LAYOUT_MODE_PHYSICAL: + scale = 1.0; + break; ++ case META_LOGICAL_MONITOR_LAYOUT_MODE_GLOBAL_UI_LOGICAL: ++ break; + } + + crtc_mode = monitor_crtc_mode->crtc_mode; +@@ -248,6 +262,7 @@ assign_monitor_crtc (MetaMonitor *monitor, .mode = crtc_mode, .layout = crtc_layout, + .transform = crtc_hw_transform, + .scale = scale, - .transform = crtc_transform, .outputs = g_ptr_array_new () }; -@@ -525,7 +538,11 @@ meta_monitor_config_manager_get_stored (MetaMonitorConfigManager *config_manager + g_ptr_array_add (crtc_info->outputs, output); +@@ -528,7 +543,11 @@ meta_monitor_config_manager_get_stored (MetaMonitorConfigManager *config_manager typedef enum _MonitorMatchRule { MONITOR_MATCH_ALL = 0, @@ -168,7 +174,7 @@ } MonitorMatchRule; static MetaMonitor * -@@ -659,11 +676,68 @@ get_monitor_transform (MetaMonitorManager *monitor_manager, +@@ -662,11 +681,68 @@ get_monitor_transform (MetaMonitorManager *monitor_manager, } } @@ -237,7 +243,7 @@ MetaLogicalMonitorConfig *primary_logical_monitor_config, MetaLogicalMonitorLayoutMode layout_mode) { -@@ -683,6 +757,7 @@ create_preferred_logical_monitor_config (MetaMonitorManager *monitor_ma +@@ -686,6 +762,7 @@ create_preferred_logical_monitor_config (MetaMonitorManager *monitor_ma scale = primary_logical_monitor_config->scale; else scale = meta_monitor_manager_calculate_monitor_mode_scale (monitor_manager, @@ -245,7 +251,7 @@ monitor, mode); -@@ -692,6 +767,13 @@ create_preferred_logical_monitor_config (MetaMonitorManager *monitor_ma +@@ -695,6 +772,13 @@ create_preferred_logical_monitor_config (MetaMonitorManager *monitor_ma width = (int) roundf (width / scale); height = (int) roundf (height / scale); break; @@ -259,7 +265,7 @@ case META_LOGICAL_MONITOR_LAYOUT_MODE_PHYSICAL: break; } -@@ -730,6 +812,7 @@ meta_monitor_config_manager_create_linear (MetaMonitorConfigManager *config_mana +@@ -733,6 +817,7 @@ meta_monitor_config_manager_create_linear (MetaMonitorConfigManager *config_mana MetaMonitor *primary_monitor; MetaLogicalMonitorLayoutMode layout_mode; MetaLogicalMonitorConfig *primary_logical_monitor_config; @@ -267,7 +273,7 @@ int x; GList *monitors; GList *l; -@@ -740,10 +823,16 @@ meta_monitor_config_manager_create_linear (MetaMonitorConfigManager *config_mana +@@ -743,10 +828,16 @@ meta_monitor_config_manager_create_linear (MetaMonitorConfigManager *config_mana layout_mode = meta_monitor_manager_get_default_layout_mode (monitor_manager); @@ -284,7 +290,7 @@ NULL, layout_mode); primary_logical_monitor_config->is_primary = TRUE; -@@ -768,6 +857,7 @@ meta_monitor_config_manager_create_linear (MetaMonitorConfigManager *config_mana +@@ -771,6 +862,7 @@ meta_monitor_config_manager_create_linear (MetaMonitorConfigManager *config_mana create_preferred_logical_monitor_config (monitor_manager, monitor, x, 0, @@ -292,7 +298,7 @@ primary_logical_monitor_config, layout_mode); logical_monitor_configs = g_list_append (logical_monitor_configs, -@@ -790,6 +880,7 @@ meta_monitor_config_manager_create_fallback (MetaMonitorConfigManager *config_ma +@@ -793,6 +885,7 @@ meta_monitor_config_manager_create_fallback (MetaMonitorConfigManager *config_ma GList *logical_monitor_configs; MetaLogicalMonitorLayoutMode layout_mode; MetaLogicalMonitorConfig *primary_logical_monitor_config; @@ -300,7 +306,7 @@ primary_monitor = find_primary_monitor (monitor_manager); if (!primary_monitor) -@@ -797,10 +888,16 @@ meta_monitor_config_manager_create_fallback (MetaMonitorConfigManager *config_ma +@@ -800,10 +893,16 @@ meta_monitor_config_manager_create_fallback (MetaMonitorConfigManager *config_ma layout_mode = meta_monitor_manager_get_default_layout_mode (monitor_manager); @@ -317,7 +323,7 @@ NULL, layout_mode); primary_logical_monitor_config->is_primary = TRUE; -@@ -823,6 +920,7 @@ meta_monitor_config_manager_create_suggested (MetaMonitorConfigManager *config_m +@@ -826,6 +925,7 @@ meta_monitor_config_manager_create_suggested (MetaMonitorConfigManager *config_m GList *logical_monitor_configs; GList *region; int x, y; @@ -325,7 +331,7 @@ GList *monitors; GList *l; -@@ -835,10 +933,16 @@ meta_monitor_config_manager_create_suggested (MetaMonitorConfigManager *config_m +@@ -838,10 +938,16 @@ meta_monitor_config_manager_create_suggested (MetaMonitorConfigManager *config_m layout_mode = meta_monitor_manager_get_default_layout_mode (monitor_manager); @@ -342,7 +348,7 @@ NULL, layout_mode); primary_logical_monitor_config->is_primary = TRUE; -@@ -862,6 +966,7 @@ meta_monitor_config_manager_create_suggested (MetaMonitorConfigManager *config_m +@@ -865,6 +971,7 @@ meta_monitor_config_manager_create_suggested (MetaMonitorConfigManager *config_m create_preferred_logical_monitor_config (monitor_manager, monitor, x, y, @@ -350,7 +356,7 @@ primary_logical_monitor_config, layout_mode); logical_monitor_configs = g_list_append (logical_monitor_configs, -@@ -880,6 +985,21 @@ meta_monitor_config_manager_create_suggested (MetaMonitorConfigManager *config_m +@@ -883,6 +990,21 @@ meta_monitor_config_manager_create_suggested (MetaMonitorConfigManager *config_m region = g_list_prepend (region, &logical_monitor_config->layout); } @@ -372,7 +378,47 @@ g_list_free (region); if (!logical_monitor_configs) -@@ -1134,7 +1254,9 @@ create_for_switch_config_all_mirror (MetaMonitorConfigManager *config_manager) +@@ -1050,6 +1172,39 @@ meta_monitor_config_manager_create_for_rotate_monitor (MetaMonitorConfigManager + return create_for_builtin_display_rotation (config_manager, TRUE, META_MONITOR_TRANSFORM_NORMAL); + } + ++MetaMonitorsConfig * ++meta_monitor_config_manager_create_for_layout (MetaMonitorConfigManager *config_manager, ++ MetaMonitorsConfig *config, ++ MetaLogicalMonitorLayoutMode layout_mode) ++{ ++ MetaMonitorManager *monitor_manager = config_manager->monitor_manager; ++ GList *logical_monitor_configs; ++ GList *l; ++ ++ if (!config) ++ return NULL; ++ ++ if (config->layout_mode == layout_mode) ++ return g_object_ref (config); ++ ++ logical_monitor_configs = ++ clone_logical_monitor_config_list (config->logical_monitor_configs); ++ ++ if (layout_mode == META_LOGICAL_MONITOR_LAYOUT_MODE_PHYSICAL) ++ { ++ for (l = logical_monitor_configs; l; l = l->next) ++ { ++ MetaLogicalMonitorConfig *monitor_config = l->data; ++ monitor_config->scale = roundf (monitor_config->scale); ++ } ++ } ++ ++ return meta_monitors_config_new (monitor_manager, ++ logical_monitor_configs, ++ layout_mode, ++ META_MONITORS_CONFIG_FLAG_NONE); ++} ++ + static MetaMonitorsConfig * + create_for_switch_config_all_mirror (MetaMonitorConfigManager *config_manager) + { +@@ -1137,7 +1292,9 @@ create_for_switch_config_all_mirror (MetaMonitorConfigManager *config_manager) if (!mode) continue; @@ -383,7 +429,7 @@ best_scale = MAX (best_scale, scale); monitor_configs = g_list_prepend (monitor_configs, create_monitor_config (monitor, mode)); } -@@ -1165,12 +1287,18 @@ create_for_switch_config_external (MetaMonitorConfigManager *config_manager) +@@ -1168,12 +1325,18 @@ create_for_switch_config_external (MetaMonitorConfigManager *config_manager) MetaMonitorManager *monitor_manager = config_manager->monitor_manager; GList *logical_monitor_configs = NULL; int x = 0; @@ -402,7 +448,7 @@ monitors = meta_monitor_manager_get_monitors (monitor_manager); for (l = monitors; l; l = l->next) { -@@ -1184,6 +1312,7 @@ create_for_switch_config_external (MetaMonitorConfigManager *config_manager) +@@ -1187,6 +1350,7 @@ create_for_switch_config_external (MetaMonitorConfigManager *config_manager) create_preferred_logical_monitor_config (monitor_manager, monitor, x, 0, @@ -410,7 +456,7 @@ NULL, layout_mode); logical_monitor_configs = g_list_append (logical_monitor_configs, -@@ -1209,6 +1338,7 @@ create_for_switch_config_builtin (MetaMonitorConfigManager *config_manager) +@@ -1212,6 +1376,7 @@ create_for_switch_config_builtin (MetaMonitorConfigManager *config_manager) GList *logical_monitor_configs; MetaLogicalMonitorConfig *primary_logical_monitor_config; MetaMonitor *monitor; @@ -418,7 +464,7 @@ monitor = meta_monitor_manager_get_laptop_panel (monitor_manager); if (!monitor) -@@ -1216,10 +1346,16 @@ create_for_switch_config_builtin (MetaMonitorConfigManager *config_manager) +@@ -1219,10 +1384,16 @@ create_for_switch_config_builtin (MetaMonitorConfigManager *config_manager) layout_mode = meta_monitor_manager_get_default_layout_mode (monitor_manager); @@ -435,14 +481,48 @@ NULL, layout_mode); primary_logical_monitor_config->is_primary = TRUE; -@@ -1660,6 +1796,7 @@ meta_verify_logical_monitor_config (MetaLogicalMonitorConfig *logical_monitor +@@ -1626,6 +1797,7 @@ gboolean + meta_verify_logical_monitor_config (MetaLogicalMonitorConfig *logical_monitor_config, + MetaLogicalMonitorLayoutMode layout_mode, + MetaMonitorManager *monitor_manager, ++ float max_scale, + GError **error) + { + GList *l; +@@ -1662,6 +1834,10 @@ meta_verify_logical_monitor_config (MetaLogicalMonitorConfig *logical_monitor + switch (layout_mode) { - case META_LOGICAL_MONITOR_LAYOUT_MODE_LOGICAL: + case META_LOGICAL_MONITOR_LAYOUT_MODE_GLOBAL_UI_LOGICAL: ++ expected_mode_width /= ceilf (max_scale); ++ expected_mode_height /= ceilf (max_scale); ++ /* fall through! */ + case META_LOGICAL_MONITOR_LAYOUT_MODE_LOGICAL: expected_mode_width = roundf (expected_mode_width * logical_monitor_config->scale); - expected_mode_height = roundf (expected_mode_height * +diff --git a/src/backends/meta-monitor-config-manager.h b/src/backends/meta-monitor-config-manager.h +index 3875e04..c337a34 100644 +--- a/src/backends/meta-monitor-config-manager.h ++++ b/src/backends/meta-monitor-config-manager.h +@@ -110,6 +110,10 @@ MetaMonitorsConfig * meta_monitor_config_manager_create_for_orientation (MetaMon + META_EXPORT_TEST + MetaMonitorsConfig * meta_monitor_config_manager_create_for_rotate_monitor (MetaMonitorConfigManager *config_manager); + ++MetaMonitorsConfig * meta_monitor_config_manager_create_for_layout (MetaMonitorConfigManager *config_manager, ++ MetaMonitorsConfig *config, ++ MetaLogicalMonitorLayoutMode layout_mode); ++ + META_EXPORT_TEST + MetaMonitorsConfig * meta_monitor_config_manager_create_for_switch_config (MetaMonitorConfigManager *config_manager, + MetaMonitorSwitchConfigType config_type); +@@ -191,6 +195,7 @@ META_EXPORT_TEST + gboolean meta_verify_logical_monitor_config (MetaLogicalMonitorConfig *logical_monitor_config, + MetaLogicalMonitorLayoutMode layout_mode, + MetaMonitorManager *monitor_manager, ++ float max_scale, + GError **error); + + META_EXPORT_TEST diff --git a/src/backends/meta-monitor-config-migration.c b/src/backends/meta-monitor-config-migration.c index d619dc4..69c426c 100644 --- a/src/backends/meta-monitor-config-migration.c @@ -486,17 +566,66 @@ if (!meta_verify_monitors_config (config, monitor_manager, error)) diff --git a/src/backends/meta-monitor-config-store.c b/src/backends/meta-monitor-config-store.c -index 770bef7..c8a0e9b 100644 +index 770bef7..16cfc13 100644 --- a/src/backends/meta-monitor-config-store.c +++ b/src/backends/meta-monitor-config-store.c -@@ -534,6 +534,7 @@ derive_logical_monitor_layout (MetaLogicalMonitorConfig *logical_monitor_conf +@@ -496,6 +496,7 @@ handle_start_element (GMarkupParseContext *context, + static gboolean + derive_logical_monitor_layout (MetaLogicalMonitorConfig *logical_monitor_config, + MetaLogicalMonitorLayoutMode layout_mode, ++ float max_scale, + GError **error) + { + MetaMonitorConfig *monitor_config; +@@ -533,6 +534,10 @@ derive_logical_monitor_layout (MetaLogicalMonitorConfig *logical_monitor_conf + switch (layout_mode) { - case META_LOGICAL_MONITOR_LAYOUT_MODE_LOGICAL: + case META_LOGICAL_MONITOR_LAYOUT_MODE_GLOBAL_UI_LOGICAL: ++ width *= ceilf (max_scale); ++ height *= ceilf (max_scale); ++ /* fall through! */ + case META_LOGICAL_MONITOR_LAYOUT_MODE_LOGICAL: width = roundf (width / logical_monitor_config->scale); height = roundf (height / logical_monitor_config->scale); - break; +@@ -740,6 +745,7 @@ handle_end_element (GMarkupParseContext *context, + GList *l; + MetaLogicalMonitorLayoutMode layout_mode; + MetaMonitorsConfigFlag config_flags = META_MONITORS_CONFIG_FLAG_NONE; ++ float max_scale = 1.0f; + + g_assert (g_str_equal (element_name, "configuration")); + +@@ -749,18 +755,29 @@ handle_end_element (GMarkupParseContext *context, + layout_mode = + meta_monitor_manager_get_default_layout_mode (store->monitor_manager); + ++ if (layout_mode == META_LOGICAL_MONITOR_LAYOUT_MODE_GLOBAL_UI_LOGICAL) ++ { ++ for (l = parser->current_logical_monitor_configs; l; l = l->next) ++ { ++ MetaLogicalMonitorConfig *logical_monitor_config = l->data; ++ max_scale = MAX (max_scale, logical_monitor_config->scale); ++ } ++ } ++ + for (l = parser->current_logical_monitor_configs; l; l = l->next) + { + MetaLogicalMonitorConfig *logical_monitor_config = l->data; + + if (!derive_logical_monitor_layout (logical_monitor_config, + layout_mode, ++ max_scale, + error)) + return; + + if (!meta_verify_logical_monitor_config (logical_monitor_config, + layout_mode, + store->monitor_manager, ++ max_scale, + error)) + return; + } diff --git a/src/backends/meta-monitor-manager-dummy.c b/src/backends/meta-monitor-manager-dummy.c index 2ddd826..fc29b45 100644 --- a/src/backends/meta-monitor-manager-dummy.c @@ -669,7 +798,7 @@ meta_monitor_manager_get_capabilities (MetaMonitorManager *manager); diff --git a/src/backends/meta-monitor-manager.c b/src/backends/meta-monitor-manager.c -index 3505573..7c77020 100644 +index 3505573..98ea9de 100644 --- a/src/backends/meta-monitor-manager.c +++ b/src/backends/meta-monitor-manager.c @@ -111,8 +111,18 @@ static gboolean @@ -723,12 +852,12 @@ { - MetaLogicalMonitorConfig *logical_monitor_config; + GList *l; -+ + +- logical_monitor_config = config->logical_monitor_configs->data; + for (l = config->logical_monitor_configs; l; l = l->next) + { + MetaLogicalMonitorConfig *monitor_config = l->data; - -- logical_monitor_config = config->logical_monitor_configs->data; ++ + if (is_global_scale_matching_in_config (config, monitor_config->scale)) + return monitor_config->scale; + } @@ -791,18 +920,18 @@ + scale)) + return scale; + } -+ + +- if (!monitor) +- return 1.0; + for (l = manager->monitors; l; l = l->next) + { + MetaMonitor *other_monitor = l->data; + float monitor_scale; -- if (!monitor) -- return 1.0; +- return calculate_monitor_scale (manager, monitor); + if (other_monitor == monitor || !meta_monitor_is_active (other_monitor)) + continue; - -- return calculate_monitor_scale (manager, monitor); ++ + monitor_scale = calculate_monitor_scale (manager, other_monitor); + if (meta_monitor_manager_is_scale_supported_by_other_monitors (manager, + other_monitor, @@ -814,7 +943,7 @@ } static float -@@ -258,6 +340,44 @@ derive_scale_from_config (MetaMonitorManager *manager, +@@ -258,6 +340,49 @@ derive_scale_from_config (MetaMonitorManager *manager, return 1.0; } @@ -823,13 +952,18 @@ + MetaMonitor *monitor, + float *scale) +{ ++ MetaMonitorManagerCapability capabilities; + MetaMonitorMode *monitor_mode; + float threshold; + MetaOutput *output; + MetaCrtc *crtc; + -+ if (!(meta_monitor_manager_get_capabilities (manager) & -+ META_MONITOR_MANAGER_CAPABILITY_NATIVE_OUTPUT_SCALING)) ++ capabilities = meta_monitor_manager_get_capabilities (manager); ++ ++ if (!(capabilities & META_MONITOR_MANAGER_CAPABILITY_NATIVE_OUTPUT_SCALING)) ++ return FALSE; ++ ++ if (!(capabilities & META_MONITOR_MANAGER_CAPABILITY_LAYOUT_MODE)) + return FALSE; + + output = meta_monitor_get_main_output (monitor); @@ -859,12 +993,14 @@ static void meta_monitor_manager_rebuild_logical_monitors_derived (MetaMonitorManager *manager, MetaMonitorsConfig *config) -@@ -306,10 +426,16 @@ meta_monitor_manager_rebuild_logical_monitors_derived (MetaMonitorManager *manag +@@ -305,11 +430,17 @@ meta_monitor_manager_rebuild_logical_monitors_derived (MetaMonitorManager *manag + float scale; if (use_global_scale) - scale = global_scale; +- scale = global_scale; - else if (config) - scale = derive_scale_from_config (manager, config, &layout); ++ scale = roundf (global_scale); else - scale = calculate_monitor_scale (manager, monitor); + { @@ -879,7 +1015,7 @@ g_assert (scale > 0); -@@ -411,16 +537,24 @@ meta_monitor_manager_is_headless (MetaMonitorManager *manager) +@@ -411,16 +542,24 @@ meta_monitor_manager_is_headless (MetaMonitorManager *manager) } float @@ -910,7 +1046,7 @@ } float * -@@ -534,7 +668,8 @@ static gboolean +@@ -534,7 +673,8 @@ static gboolean should_use_stored_config (MetaMonitorManager *manager) { return (manager->in_init || @@ -920,7 +1056,119 @@ } MetaMonitorsConfig * -@@ -726,6 +861,8 @@ experimental_features_changed (MetaSettings *settings, +@@ -546,6 +686,8 @@ meta_monitor_manager_ensure_configured (MetaMonitorManager *manager) + MetaMonitorsConfigMethod method; + MetaMonitorsConfigMethod fallback_method = + META_MONITORS_CONFIG_METHOD_TEMPORARY; ++ MetaLogicalMonitorLayoutMode layout_mode = ++ meta_monitor_manager_get_default_layout_mode (manager); + + use_stored_config = should_use_stored_config (manager); + if (use_stored_config) +@@ -555,7 +697,18 @@ meta_monitor_manager_ensure_configured (MetaMonitorManager *manager) + + if (use_stored_config) + { ++ g_autoptr(MetaMonitorsConfig) new_config = NULL; ++ + config = meta_monitor_config_manager_get_stored (manager->config_manager); ++ if (config && config->layout_mode != layout_mode) ++ { ++ new_config = ++ meta_monitor_config_manager_create_for_layout (manager->config_manager, ++ config, ++ layout_mode); ++ config = new_config; ++ } ++ + if (config) + { + if (!meta_monitor_manager_apply_monitors_config (manager, +@@ -600,6 +753,16 @@ meta_monitor_manager_ensure_configured (MetaMonitorManager *manager) + { + config = g_object_ref (config); + ++ if (config && config->layout_mode != layout_mode) ++ { ++ MetaMonitorsConfig *new_config = ++ meta_monitor_config_manager_create_for_layout (manager->config_manager, ++ config, ++ layout_mode); ++ g_object_unref (config); ++ config = new_config; ++ } ++ + if (meta_monitor_manager_is_config_complete (manager, config)) + { + if (!meta_monitor_manager_apply_monitors_config (manager, +@@ -719,6 +882,66 @@ orientation_changed (MetaOrientationManager *orientation_manager, + g_object_unref (config); + } + ++static gboolean ++apply_x11_fractional_scaling_config (MetaMonitorManager *manager) ++{ ++ g_autoptr(GError) error = NULL; ++ g_autoptr(MetaMonitorsConfig) config = NULL; ++ MetaMonitorsConfig *applied_config; ++ MetaLogicalMonitorLayoutMode layout_mode = ++ meta_monitor_manager_get_default_layout_mode (manager); ++ ++ if (!META_IS_MONITOR_MANAGER_XRANDR (manager)) ++ return TRUE; ++ ++ applied_config = ++ meta_monitor_config_manager_get_current (manager->config_manager); ++ config = ++ meta_monitor_config_manager_create_for_layout (manager->config_manager, ++ applied_config, ++ layout_mode); ++ if (!config) ++ return FALSE; ++ ++ if (meta_monitor_manager_apply_monitors_config (manager, ++ config, ++ META_MONITORS_CONFIG_METHOD_PERSISTENT, ++ &error)) ++ { ++ if (config != applied_config && manager->persistent_timeout_id) ++ { ++ if (G_UNLIKELY (applied_config != ++ meta_monitor_config_manager_get_previous (manager->config_manager))) ++ { ++ g_warning ("The removed configuration doesn't match the " ++ "previously applied one, reverting may not work"); ++ } ++ else ++ { ++ g_autoptr(MetaMonitorsConfig) previous_config = NULL; ++ ++ /* The previous config we applied was just a temporary one that ++ * GNOME control center passed us while toggling the fractional ++ * scaling. So, in such case, once the configuration with the ++ * correct layout has been applied, we need to ignore the ++ * temporary one. */ ++ previous_config = ++ meta_monitor_config_manager_pop_previous (manager->config_manager); ++ ++ g_assert_true (applied_config == previous_config); ++ } ++ } ++ } ++ else ++ { ++ g_warning ("Impossible to apply the layout config %s\n", ++ error->message); ++ return FALSE; ++ } ++ ++ return TRUE; ++} ++ + static void + experimental_features_changed (MetaSettings *settings, + MetaExperimentalFeature old_experimental_features, +@@ -726,6 +949,8 @@ experimental_features_changed (MetaSettings *settings, { gboolean was_stage_views_scaled; gboolean is_stage_views_scaled; @@ -929,7 +1177,7 @@ gboolean should_reconfigure = FALSE; was_stage_views_scaled = -@@ -735,8 +872,16 @@ experimental_features_changed (MetaSettings *settings, +@@ -735,10 +960,23 @@ experimental_features_changed (MetaSettings *settings, meta_settings_is_experimental_feature_enabled ( settings, META_EXPERIMENTAL_FEATURE_SCALE_MONITOR_FRAMEBUFFER); @@ -941,13 +1189,62 @@ + settings, + META_EXPERIMENTAL_FEATURE_X11_RANDR_FRACTIONAL_SCALING); -- if (is_stage_views_scaled != was_stage_views_scaled) -+ if (is_stage_views_scaled != was_stage_views_scaled || -+ x11_scaling != was_x11_scaling) + if (is_stage_views_scaled != was_stage_views_scaled) should_reconfigure = TRUE; ++ if (was_x11_scaling != x11_scaling) ++ { ++ if (!apply_x11_fractional_scaling_config (manager)) ++ should_reconfigure = TRUE; ++ } ++ if (should_reconfigure) -@@ -1265,6 +1410,41 @@ request_persistent_confirmation (MetaMonitorManager *manager) + meta_monitor_manager_on_hotplug (manager); + +@@ -1196,6 +1434,33 @@ meta_monitor_manager_handle_get_resources (MetaDBusDisplayConfig *skeleton, + return TRUE; + } + ++static void ++restore_previous_experimental_config (MetaMonitorManager *manager, ++ MetaMonitorsConfig *previous_config) ++{ ++ MetaBackend *backend = manager->backend; ++ MetaSettings *settings = meta_backend_get_settings (backend); ++ gboolean was_fractional; ++ ++ if (!META_IS_MONITOR_MANAGER_XRANDR (manager)) ++ return; ++ ++ was_fractional = ++ previous_config->layout_mode != META_LOGICAL_MONITOR_LAYOUT_MODE_PHYSICAL; ++ ++ if (meta_settings_is_experimental_feature_enabled (settings, ++ META_EXPERIMENTAL_FEATURE_X11_RANDR_FRACTIONAL_SCALING) == was_fractional) ++ return; ++ ++ g_signal_handler_block (settings, ++ manager->experimental_features_changed_handler_id); ++ ++ meta_settings_enable_x11_fractional_scaling (settings, was_fractional); ++ ++ g_signal_handler_unblock (settings, ++ manager->experimental_features_changed_handler_id); ++} ++ + static void + restore_previous_config (MetaMonitorManager *manager) + { +@@ -1209,6 +1474,8 @@ restore_previous_config (MetaMonitorManager *manager) + { + MetaMonitorsConfigMethod method; + ++ restore_previous_experimental_config (manager, previous_config); ++ + method = META_MONITORS_CONFIG_METHOD_TEMPORARY; + if (meta_monitor_manager_apply_monitors_config (manager, + previous_config, +@@ -1265,6 +1532,41 @@ request_persistent_confirmation (MetaMonitorManager *manager) g_signal_emit (manager, signals[CONFIRM_DISPLAY_CHANGE], 0); } @@ -989,7 +1286,7 @@ #define META_DISPLAY_CONFIG_MODE_FLAGS_PREFERRED (1 << 0) #define META_DISPLAY_CONFIG_MODE_FLAGS_CURRENT (1 << 1) -@@ -1292,6 +1472,7 @@ meta_monitor_manager_handle_get_current_state (MetaDBusDisplayConfig *skeleton, +@@ -1292,6 +1594,7 @@ meta_monitor_manager_handle_get_current_state (MetaDBusDisplayConfig *skeleton, MetaMonitorManagerCapability capabilities; int ui_scaling_factor; int max_screen_width, max_screen_height; @@ -997,7 +1294,7 @@ g_variant_builder_init (&monitors_builder, G_VARIANT_TYPE (MONITORS_FORMAT)); -@@ -1338,6 +1519,7 @@ meta_monitor_manager_handle_get_current_state (MetaDBusDisplayConfig *skeleton, +@@ -1338,6 +1641,7 @@ meta_monitor_manager_handle_get_current_state (MetaDBusDisplayConfig *skeleton, preferred_scale = meta_monitor_manager_calculate_monitor_mode_scale (manager, @@ -1005,7 +1302,7 @@ monitor, monitor_mode); -@@ -1445,6 +1627,14 @@ meta_monitor_manager_handle_get_current_state (MetaDBusDisplayConfig *skeleton, +@@ -1445,6 +1749,14 @@ meta_monitor_manager_handle_get_current_state (MetaDBusDisplayConfig *skeleton, } g_variant_builder_init (&properties_builder, G_VARIANT_TYPE ("a{sv}")); @@ -1020,12 +1317,13 @@ capabilities = meta_monitor_manager_get_capabilities (manager); g_variant_builder_add (&properties_builder, "{sv}", -@@ -1463,6 +1653,13 @@ meta_monitor_manager_handle_get_current_state (MetaDBusDisplayConfig *skeleton, +@@ -1463,6 +1775,14 @@ meta_monitor_manager_handle_get_current_state (MetaDBusDisplayConfig *skeleton, "global-scale-required", g_variant_new_boolean (TRUE)); } + else if (META_IS_MONITOR_MANAGER_XRANDR (manager) && -+ capabilities & META_MONITOR_MANAGER_CAPABILITY_NATIVE_OUTPUT_SCALING) ++ (capabilities & META_MONITOR_MANAGER_CAPABILITY_NATIVE_OUTPUT_SCALING) && ++ (capabilities & META_MONITOR_MANAGER_CAPABILITY_LAYOUT_MODE)) + { + g_variant_builder_add (&properties_builder, "{sv}", + "x11-fractional-scaling", @@ -1034,7 +1332,7 @@ ui_scaling_factor = meta_settings_get_ui_scaling_factor (settings); g_variant_builder_add (&properties_builder, "{sv}", -@@ -1507,12 +1704,14 @@ meta_monitor_manager_handle_get_current_state (MetaDBusDisplayConfig *skeleton, +@@ -1507,12 +1827,14 @@ meta_monitor_manager_handle_get_current_state (MetaDBusDisplayConfig *skeleton, #undef LOGICAL_MONITOR_FORMAT #undef LOGICAL_MONITORS_FORMAT @@ -1055,7 +1353,7 @@ { g_autofree float *supported_scales = NULL; int n_supported_scales; -@@ -1526,8 +1725,66 @@ meta_monitor_manager_is_scale_supported (MetaMonitorManager *manager, +@@ -1526,8 +1848,66 @@ meta_monitor_manager_is_scale_supported (MetaMonitorManager *manager, &n_supported_scales); for (i = 0; i < n_supported_scales; i++) { @@ -1124,7 +1422,7 @@ } return FALSE; -@@ -1571,11 +1828,11 @@ meta_monitor_manager_is_config_applicable (MetaMonitorManager *manager, +@@ -1571,11 +1951,11 @@ meta_monitor_manager_is_config_applicable (MetaMonitorManager *manager, return FALSE; } @@ -1141,7 +1439,7 @@ { g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Scale not supported by backend"); -@@ -1796,6 +2053,7 @@ derive_logical_monitor_size (MetaMonitorConfig *monitor_config, +@@ -1796,6 +2176,7 @@ derive_logical_monitor_size (MetaMonitorConfig *monitor_config, switch (layout_mode) { case META_LOGICAL_MONITOR_LAYOUT_MODE_LOGICAL: @@ -1149,7 +1447,20 @@ width = roundf (width / scale); height = roundf (height / scale); break; -@@ -1918,6 +2176,7 @@ is_valid_layout_mode (MetaLogicalMonitorLayoutMode layout_mode) +@@ -1895,9 +2276,11 @@ create_logical_monitor_config_from_variant (MetaMonitorManager *manager + .monitor_configs = monitor_configs + }; + +- if (!meta_verify_logical_monitor_config (logical_monitor_config, ++ if (layout_mode != META_LOGICAL_MONITOR_LAYOUT_MODE_GLOBAL_UI_LOGICAL && ++ !meta_verify_logical_monitor_config (logical_monitor_config, + layout_mode, + manager, ++ 1.0f, + error)) + { + meta_logical_monitor_config_free (logical_monitor_config); +@@ -1918,6 +2301,7 @@ is_valid_layout_mode (MetaLogicalMonitorLayoutMode layout_mode) { case META_LOGICAL_MONITOR_LAYOUT_MODE_LOGICAL: case META_LOGICAL_MONITOR_LAYOUT_MODE_PHYSICAL: @@ -1157,7 +1468,7 @@ return TRUE; } -@@ -1940,6 +2199,7 @@ meta_monitor_manager_handle_apply_monitors_config (MetaDBusDisplayConfig *skelet +@@ -1940,6 +2324,7 @@ meta_monitor_manager_handle_apply_monitors_config (MetaDBusDisplayConfig *skelet MetaMonitorsConfig *config; GList *logical_monitor_configs = NULL; GError *error = NULL; @@ -1165,7 +1476,7 @@ if (serial != manager->serial) { -@@ -2011,10 +2271,26 @@ meta_monitor_manager_handle_apply_monitors_config (MetaDBusDisplayConfig *skelet +@@ -2011,10 +2396,42 @@ meta_monitor_manager_handle_apply_monitors_config (MetaDBusDisplayConfig *skelet return TRUE; } @@ -1182,17 +1493,33 @@ + for (l = logical_monitor_configs; l; l = l->next) + { + MetaLogicalMonitorConfig *logical_monitor_config = l->data; ++ + logical_monitor_config->layout.width = + roundf (logical_monitor_config->layout.width * ui_scale); + logical_monitor_config->layout.height = + roundf (logical_monitor_config->layout.height * ui_scale); ++ ++ if (!meta_verify_logical_monitor_config (logical_monitor_config, ++ manager->layout_mode, ++ manager, ++ ui_scale, ++ &error)) ++ { ++ g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, ++ G_DBUS_ERROR_INVALID_ARGS, ++ "%s", error->message); ++ g_error_free (error); ++ g_list_free_full (logical_monitor_configs, ++ (GDestroyNotify) meta_logical_monitor_config_free); ++ return TRUE; ++ } + } + } + config = meta_monitors_config_new (manager, logical_monitor_configs, layout_mode, -@@ -2452,12 +2728,6 @@ meta_monitor_manager_get_laptop_panel (MetaMonitorManager *manager) +@@ -2452,12 +2869,6 @@ meta_monitor_manager_get_laptop_panel (MetaMonitorManager *manager) return find_monitor (manager, meta_monitor_is_laptop_panel); } @@ -1205,7 +1532,7 @@ MetaMonitor * meta_monitor_manager_get_monitor_from_connector (MetaMonitorManager *manager, const char *connector) -@@ -2633,6 +2903,10 @@ rebuild_monitors (MetaMonitorManager *manager) +@@ -2633,6 +3044,10 @@ rebuild_monitors (MetaMonitorManager *manager) { GList *gpus; GList *l; @@ -1216,7 +1543,7 @@ if (manager->monitors) { -@@ -2650,7 +2924,7 @@ rebuild_monitors (MetaMonitorManager *manager) +@@ -2650,7 +3065,7 @@ rebuild_monitors (MetaMonitorManager *manager) { MetaOutput *output = k->data; @@ -1225,7 +1552,7 @@ { if (is_main_tiled_monitor_output (output)) { -@@ -2856,7 +3130,7 @@ meta_monitor_manager_update_logical_state_derived (MetaMonitorManager *manager, +@@ -2856,7 +3271,7 @@ meta_monitor_manager_update_logical_state_derived (MetaMonitorManager *manager, else manager->current_switch_config = META_MONITOR_SWITCH_CONFIG_UNKNOWN; @@ -1234,7 +1561,7 @@ meta_monitor_manager_rebuild_logical_monitors_derived (manager, config); } -@@ -2865,10 +3139,14 @@ void +@@ -2865,10 +3280,14 @@ void meta_monitor_manager_rebuild_derived (MetaMonitorManager *manager, MetaMonitorsConfig *config) { @@ -1250,7 +1577,7 @@ return; diff --git a/src/backends/meta-monitor.c b/src/backends/meta-monitor.c -index f4d71f0..a643728 100644 +index 07857e0..bd6da5c 100644 --- a/src/backends/meta-monitor.c +++ b/src/backends/meta-monitor.c @@ -703,8 +703,11 @@ meta_monitor_normal_get_suggested_position (MetaMonitor *monitor, @@ -1398,10 +1725,10 @@ META_EXPORT_TEST float * meta_monitor_calculate_supported_scales (MetaMonitor *monitor, diff --git a/src/backends/meta-settings-private.h b/src/backends/meta-settings-private.h -index 7d610d5..a78d61e 100644 +index 7d610d5..a7241ce 100644 --- a/src/backends/meta-settings-private.h +++ b/src/backends/meta-settings-private.h -@@ -35,8 +35,15 @@ typedef enum _MetaExperimentalFeature +@@ -35,8 +35,16 @@ typedef enum _MetaExperimentalFeature META_EXPERIMENTAL_FEATURE_KMS_MODIFIERS = (1 << 1), META_EXPERIMENTAL_FEATURE_RT_SCHEDULER = (1 << 2), META_EXPERIMENTAL_FEATURE_AUTOSTART_XWAYLAND = (1 << 3), @@ -1410,22 +1737,26 @@ +typedef enum _MetaX11ScaleMode +{ ++ META_X11_SCALE_MODE_NONE = 0, + META_X11_SCALE_MODE_UP = 1, -+ META_X11_SCALE_MODE_UI_DOWN, ++ META_X11_SCALE_MODE_UI_DOWN = 2, +} MetaX11ScaleMode; + #define META_TYPE_SETTINGS (meta_settings_get_type ()) G_DECLARE_FINAL_TYPE (MetaSettings, meta_settings, META, SETTINGS, GObject) -@@ -69,4 +76,6 @@ void meta_settings_get_xwayland_grab_patterns (MetaSettings *settings, +@@ -69,4 +77,9 @@ void meta_settings_get_xwayland_grab_patterns (MetaSettings *settings, gboolean meta_settings_are_xwayland_grabs_allowed (MetaSettings *settings); +MetaX11ScaleMode meta_settings_get_x11_scale_mode (MetaSettings *settings); + ++void meta_settings_enable_x11_fractional_scaling (MetaSettings *settings, ++ gboolean enabled); ++ #endif /* META_SETTINGS_PRIVATE_H */ diff --git a/src/backends/meta-settings.c b/src/backends/meta-settings.c -index 1cc000e..add7ac7 100644 +index 1cc000e..cd9b3df 100644 --- a/src/backends/meta-settings.c +++ b/src/backends/meta-settings.c @@ -40,6 +40,7 @@ enum @@ -1453,7 +1784,7 @@ }; G_DEFINE_TYPE (MetaSettings, meta_settings, G_TYPE_OBJECT) -@@ -77,14 +81,33 @@ calculate_ui_scaling_factor (MetaSettings *settings) +@@ -77,14 +81,39 @@ calculate_ui_scaling_factor (MetaSettings *settings) { MetaMonitorManager *monitor_manager = meta_backend_get_monitor_manager (settings->backend); @@ -1464,23 +1795,28 @@ - if (!primary_logical_monitor) - return 1; + if (!meta_is_wayland_compositor () && -+ (settings->experimental_features & -+ META_EXPERIMENTAL_FEATURE_X11_RANDR_FRACTIONAL_SCALING)) ++ monitor_manager && ++ (meta_monitor_manager_get_capabilities (monitor_manager) & ++ META_MONITOR_MANAGER_CAPABILITY_LAYOUT_MODE)) + { -+ float scale = 1; -+ -+ if (monitor_manager && -+ settings->x11_scale_mode == META_X11_SCALE_MODE_UI_DOWN) -+ scale = -+ ceilf (meta_monitor_manager_get_maximum_crtc_scale (monitor_manager)); ++ MetaLogicalMonitorLayoutMode layout_mode = ++ meta_monitor_manager_get_default_layout_mode (monitor_manager); + -+ return scale; ++ if (layout_mode == META_LOGICAL_MONITOR_LAYOUT_MODE_GLOBAL_UI_LOGICAL) ++ { ++ return ++ ceilf (meta_monitor_manager_get_maximum_crtc_scale (monitor_manager)); ++ } ++ else if (layout_mode == META_LOGICAL_MONITOR_LAYOUT_MODE_LOGICAL) ++ { ++ return 1.0f; ++ } + } -+ else if (monitor_manager) ++ ++ if (monitor_manager) + { + MetaLogicalMonitor *primary_logical_monitor; - -- return (int) meta_logical_monitor_get_scale (primary_logical_monitor); ++ + primary_logical_monitor = + meta_monitor_manager_get_primary_logical_monitor (monitor_manager); + if (!primary_logical_monitor) @@ -1488,12 +1824,100 @@ + + return (int) meta_logical_monitor_get_scale (primary_logical_monitor); + } -+ + +- return (int) meta_logical_monitor_get_scale (primary_logical_monitor); + return 1; } static gboolean -@@ -270,6 +293,8 @@ experimental_features_handler (GVariant *features_variant, +@@ -232,6 +261,76 @@ meta_settings_override_experimental_features (MetaSettings *settings) + settings->experimental_features_overridden = TRUE; + } + ++static gboolean ++update_x11_scale_mode (MetaSettings *settings) ++{ ++ MetaX11ScaleMode scale_mode; ++ ++ if (!(settings->experimental_features & ++ META_EXPERIMENTAL_FEATURE_X11_RANDR_FRACTIONAL_SCALING)) ++ { ++ scale_mode = META_X11_SCALE_MODE_NONE; ++ } ++ else ++ { ++ scale_mode = ++ g_settings_get_enum (settings->x11_settings, "fractional-scale-mode"); ++ } ++ ++ if (settings->x11_scale_mode != scale_mode) ++ { ++ settings->x11_scale_mode = scale_mode; ++ return TRUE; ++ } ++ ++ return FALSE; ++} ++ ++void meta_settings_enable_x11_fractional_scaling (MetaSettings *settings, ++ gboolean enable) ++{ ++ g_auto(GStrv) existing_features = NULL; ++ gboolean have_fractional_scaling = FALSE; ++ g_autoptr(GVariantBuilder) builder = NULL; ++ MetaExperimentalFeature old_experimental_features; ++ ++ if (enable == meta_settings_is_experimental_feature_enabled (settings, ++ META_EXPERIMENTAL_FEATURE_X11_RANDR_FRACTIONAL_SCALING)) ++ return; ++ ++ /* Change the internal value now, as we don't want to wait for gsettings */ ++ old_experimental_features = settings->experimental_features; ++ settings->experimental_features |= ++ META_EXPERIMENTAL_FEATURE_X11_RANDR_FRACTIONAL_SCALING; ++ ++ update_x11_scale_mode (settings); ++ ++ g_signal_emit (settings, signals[EXPERIMENTAL_FEATURES_CHANGED], 0, ++ (unsigned int) old_experimental_features); ++ ++ /* Add or remove the fractional scaling feature from mutter */ ++ existing_features = g_settings_get_strv (settings->mutter_settings, ++ "experimental-features"); ++ builder = g_variant_builder_new (G_VARIANT_TYPE ("as")); ++ for (int i = 0; existing_features[i] != NULL; i++) ++ { ++ if (g_strcmp0 (existing_features[i], "x11-randr-fractional-scaling") == 0) ++ { ++ if (enable) ++ have_fractional_scaling = TRUE; ++ else ++ continue; ++ } ++ ++ g_variant_builder_add (builder, "s", existing_features[i]); ++ } ++ if (enable && !have_fractional_scaling) ++ g_variant_builder_add (builder, "s", "x11-randr-fractional-scaling"); ++ ++ g_settings_set_value (settings->mutter_settings, "experimental-features", ++ g_variant_builder_end (builder)); ++} ++ + void + meta_settings_enable_experimental_feature (MetaSettings *settings, + MetaExperimentalFeature feature) +@@ -239,6 +338,9 @@ meta_settings_enable_experimental_feature (MetaSettings *settings, + g_assert (settings->experimental_features_overridden); + + settings->experimental_features |= feature; ++ ++ if (update_x11_scale_mode (settings)) ++ g_signal_emit (settings, signals[X11_SCALE_MODE_CHANGED], 0, NULL); + } + + static gboolean +@@ -270,6 +372,8 @@ experimental_features_handler (GVariant *features_variant, feature = META_EXPERIMENTAL_FEATURE_RT_SCHEDULER; else if (g_str_equal (feature_str, "autostart-xwayland")) feature = META_EXPERIMENTAL_FEATURE_AUTOSTART_XWAYLAND; @@ -1502,33 +1926,34 @@ if (feature) g_message ("Enabling experimental feature '%s'", feature_str); -@@ -403,6 +428,25 @@ wayland_settings_changed (GSettings *wayland_settings, +@@ -282,6 +386,7 @@ experimental_features_handler (GVariant *features_variant, + if (features != settings->experimental_features) + { + settings->experimental_features = features; ++ update_x11_scale_mode (settings); + *result = GINT_TO_POINTER (TRUE); + } + else +@@ -403,6 +508,18 @@ wayland_settings_changed (GSettings *wayland_settings, } } +static void -+update_x11_scale_mode (MetaSettings *settings) -+{ -+ settings->x11_scale_mode = -+ g_settings_get_enum (settings->x11_settings, "fractional-scale-mode"); -+} -+ -+static void +x11_settings_changed (GSettings *wayland_settings, + gchar *key, + MetaSettings *settings) +{ + if (g_str_equal (key, "fractional-scale-mode")) + { -+ update_x11_scale_mode (settings); -+ g_signal_emit (settings, signals[X11_SCALE_MODE_CHANGED], 0, NULL); ++ if (update_x11_scale_mode (settings)) ++ g_signal_emit (settings, signals[X11_SCALE_MODE_CHANGED], 0, NULL); + } +} + void meta_settings_get_xwayland_grab_patterns (MetaSettings *settings, GPtrArray **whitelist_patterns, -@@ -418,6 +462,12 @@ meta_settings_are_xwayland_grabs_allowed (MetaSettings *settings) +@@ -418,6 +535,12 @@ meta_settings_are_xwayland_grabs_allowed (MetaSettings *settings) return (settings->xwayland_allow_grabs); } @@ -1541,7 +1966,7 @@ MetaSettings * meta_settings_new (MetaBackend *backend) { -@@ -437,6 +487,7 @@ meta_settings_dispose (GObject *object) +@@ -437,6 +560,7 @@ meta_settings_dispose (GObject *object) g_clear_object (&settings->mutter_settings); g_clear_object (&settings->interface_settings); g_clear_object (&settings->wayland_settings); @@ -1549,7 +1974,7 @@ g_clear_pointer (&settings->xwayland_grab_whitelist_patterns, g_ptr_array_unref); g_clear_pointer (&settings->xwayland_grab_blacklist_patterns, -@@ -460,6 +511,10 @@ meta_settings_init (MetaSettings *settings) +@@ -460,6 +584,10 @@ meta_settings_init (MetaSettings *settings) g_signal_connect (settings->wayland_settings, "changed", G_CALLBACK (wayland_settings_changed), settings); @@ -1560,15 +1985,7 @@ /* Chain up inter-dependent settings. */ g_signal_connect (settings, "global-scaling-factor-changed", -@@ -471,6 +526,7 @@ meta_settings_init (MetaSettings *settings) - update_experimental_features (settings); - update_xwayland_grab_access_rules (settings); - update_xwayland_allow_grabs (settings); -+ update_x11_scale_mode (settings); - } - - static void -@@ -525,6 +581,14 @@ meta_settings_class_init (MetaSettingsClass *klass) +@@ -525,6 +653,14 @@ meta_settings_class_init (MetaSettingsClass *klass) NULL, NULL, NULL, G_TYPE_NONE, 0); @@ -1584,10 +2001,10 @@ g_signal_new ("experimental-features-changed", G_TYPE_FROM_CLASS (object_class), diff --git a/src/backends/native/meta-monitor-manager-kms.c b/src/backends/native/meta-monitor-manager-kms.c -index 6dcba64..8e3884f 100644 +index e3c15f4..b7d4681 100644 --- a/src/backends/native/meta-monitor-manager-kms.c +++ b/src/backends/native/meta-monitor-manager-kms.c -@@ -510,20 +510,8 @@ meta_monitor_manager_kms_is_transform_handled (MetaMonitorManager *manager, +@@ -518,20 +518,8 @@ meta_monitor_manager_kms_is_transform_handled (MetaMonitorManager *manager, return meta_crtc_kms_is_transform_handled (crtc, transform); } @@ -1610,7 +2027,7 @@ { MetaMonitorScalesConstraint constraints = META_MONITOR_SCALES_CONSTRAINT_NONE; -@@ -531,12 +519,38 @@ meta_monitor_manager_kms_calculate_supported_scales (MetaMonitorManager +@@ -539,12 +527,38 @@ meta_monitor_manager_kms_calculate_supported_scales (MetaMonitorManager switch (layout_mode) { case META_LOGICAL_MONITOR_LAYOUT_MODE_LOGICAL: @@ -1649,7 +2066,7 @@ return meta_monitor_calculate_supported_scales (monitor, monitor_mode, constraints, n_supported_scales); -@@ -548,7 +562,7 @@ meta_monitor_manager_kms_get_capabilities (MetaMonitorManager *manager) +@@ -556,7 +570,7 @@ meta_monitor_manager_kms_get_capabilities (MetaMonitorManager *manager) MetaBackend *backend = meta_monitor_manager_get_backend (manager); MetaSettings *settings = meta_backend_get_settings (backend); MetaMonitorManagerCapability capabilities = @@ -1659,7 +2076,7 @@ if (meta_settings_is_experimental_feature_enabled ( settings, diff --git a/src/backends/x11/meta-crtc-xrandr.c b/src/backends/x11/meta-crtc-xrandr.c -index 89115ca..f048434 100644 +index 89115ca..8c875fc 100644 --- a/src/backends/x11/meta-crtc-xrandr.c +++ b/src/backends/x11/meta-crtc-xrandr.c @@ -36,6 +36,7 @@ @@ -1715,7 +2132,7 @@ + xdisplay = meta_monitor_manager_xrandr_get_xdisplay (monitor_manager_xrandr); + xcb_conn = XGetXCBConnection (xdisplay); + -+ if (scale != 1.0f) ++ if (fabsf (scale - 1.0f) > 0.001) + { + scale_filter = FilterGood; + transformation.matrix11 = DOUBLE_TO_FIXED (1.0 / scale); @@ -1742,7 +2159,7 @@ return TRUE; } -@@ -228,11 +287,31 @@ meta_crtc_destroy_notify (MetaCrtc *crtc) +@@ -228,11 +287,32 @@ meta_crtc_destroy_notify (MetaCrtc *crtc) g_free (crtc->driver_private); } @@ -1774,23 +2191,27 @@ + XRRCrtcInfo *xrandr_crtc, + RRCrtc crtc_id, + XRRScreenResources *resources, -+ XRRCrtcTransformAttributes *transform_attributes) ++ XRRCrtcTransformAttributes *transform_attributes, ++ float scale_multiplier) { MetaGpu *gpu = META_GPU (gpu_xrandr); MetaBackend *backend = meta_gpu_get_backend (gpu); -@@ -282,6 +361,7 @@ meta_create_xrandr_crtc (MetaGpuXrandr *gpu_xrandr, +@@ -282,6 +362,10 @@ meta_create_xrandr_crtc (MetaGpuXrandr *gpu_xrandr, crtc->is_dirty = FALSE; crtc->all_transforms = meta_monitor_transform_from_xrandr_all (xrandr_crtc->rotations); + crtc->scale = meta_monitor_scale_from_transformation (transform_attributes); ++ ++ if (scale_multiplier > 0.0f) ++ crtc->scale *= scale_multiplier; modes = meta_gpu_get_modes (crtc->gpu); for (i = 0; i < (unsigned int) resources->nmode; i++) diff --git a/src/backends/x11/meta-crtc-xrandr.h b/src/backends/x11/meta-crtc-xrandr.h -index 3226378..fb9ab8d 100644 +index 3226378..c968004 100644 --- a/src/backends/x11/meta-crtc-xrandr.h +++ b/src/backends/x11/meta-crtc-xrandr.h -@@ -44,9 +44,14 @@ gboolean meta_crtc_xrandr_is_assignment_changed (MetaCrtc *crtc, +@@ -44,9 +44,15 @@ gboolean meta_crtc_xrandr_is_assignment_changed (MetaCrtc *crtc, MetaCrtcMode * meta_crtc_xrandr_get_current_mode (MetaCrtc *crtc); @@ -1806,11 +2227,12 @@ + XRRCrtcInfo *xrandr_crtc, + RRCrtc crtc_id, + XRRScreenResources *resources, -+ XRRCrtcTransformAttributes *transform_attributes); ++ XRRCrtcTransformAttributes *transform_attributes, ++ float scale_multiplier); #endif /* META_CRTC_XRANDR_H */ diff --git a/src/backends/x11/meta-gpu-xrandr.c b/src/backends/x11/meta-gpu-xrandr.c -index e90189d..75d6ae0 100644 +index e90189d..65a3c30 100644 --- a/src/backends/x11/meta-gpu-xrandr.c +++ b/src/backends/x11/meta-gpu-xrandr.c @@ -44,6 +44,8 @@ struct _MetaGpuXrandr @@ -1922,7 +2344,7 @@ &gpu_xrandr->max_screen_width, &gpu_xrandr->max_screen_height); -@@ -154,17 +219,33 @@ meta_gpu_xrandr_read_current (MetaGpu *gpu, +@@ -154,17 +219,32 @@ meta_gpu_xrandr_read_current (MetaGpu *gpu, } meta_gpu_take_modes (gpu, modes); @@ -1951,12 +2373,36 @@ crtc = meta_create_xrandr_crtc (gpu_xrandr, - xrandr_crtc, crtc_id, resources); + xrandr_crtc, crtc_id, resources, -+ transform_attributes); -+ crtc->scale *= dpi_scale; ++ transform_attributes, dpi_scale); + XFree (transform_attributes); XRRFreeCrtcInfo (xrandr_crtc); crtcs = g_list_append (crtcs, crtc); +@@ -172,6 +252,24 @@ meta_gpu_xrandr_read_current (MetaGpu *gpu, + + meta_gpu_take_crtcs (gpu, crtcs); + ++ if (has_transform && dpi_scale == 1 && ++ meta_monitor_manager_get_default_layout_mode (monitor_manager) == ++ META_LOGICAL_MONITOR_LAYOUT_MODE_GLOBAL_UI_LOGICAL) ++ { ++ dpi_scale = ++ ceilf (meta_monitor_manager_get_maximum_crtc_scale (monitor_manager)); ++ ++ if (dpi_scale > 1) ++ { ++ for (l = crtcs; l; l = l->next) ++ { ++ MetaCrtc *crtc = l->data; ++ ++ crtc->scale *= dpi_scale; ++ } ++ } ++ } ++ + primary_output = XRRGetOutputPrimary (xdisplay, + DefaultRootWindow (xdisplay)); + diff --git a/src/backends/x11/meta-gpu-xrandr.h b/src/backends/x11/meta-gpu-xrandr.h index 2086f86..a1f3b48 100644 --- a/src/backends/x11/meta-gpu-xrandr.h @@ -1973,7 +2419,7 @@ int *max_width, int *max_height); diff --git a/src/backends/x11/meta-monitor-manager-xrandr.c b/src/backends/x11/meta-monitor-manager-xrandr.c -index 5c16189..da3225f 100644 +index 6cdcbbe..0290475 100644 --- a/src/backends/x11/meta-monitor-manager-xrandr.c +++ b/src/backends/x11/meta-monitor-manager-xrandr.c @@ -63,6 +63,9 @@ @@ -2020,7 +2466,7 @@ } static GBytes * -@@ -186,6 +189,58 @@ meta_monitor_manager_xrandr_set_power_save_mode (MetaMonitorManager *manager, +@@ -186,6 +189,81 @@ meta_monitor_manager_xrandr_set_power_save_mode (MetaMonitorManager *manager, DPMSSetTimeouts (manager_xrandr->xdisplay, 0, 0, 0); } @@ -2032,6 +2478,9 @@ +{ + MetaMonitorManager *manager = META_MONITOR_MANAGER (manager_xrandr); + MetaGpu *gpu = meta_monitor_manager_xrandr_get_gpu (manager_xrandr); ++ xcb_connection_t *xcb_conn; ++ xcb_generic_error_t *xcb_error; ++ xcb_void_cookie_t xcb_cookie; + Screen *screen; + int min_width; + int min_height; @@ -2066,20 +2515,40 @@ + width_mm == WidthMMOfScreen (screen) && height_mm == HeightMMOfScreen (screen)) + return; + -+ XGrabServer (manager_xrandr->xdisplay); -+ XRRSetScreenSize (manager_xrandr->xdisplay, -+ DefaultRootWindow (manager_xrandr->xdisplay), -+ width, height, width_mm, height_mm); -+ XUngrabServer (manager_xrandr->xdisplay); ++ xcb_conn = XGetXCBConnection (manager_xrandr->xdisplay); ++ ++ xcb_grab_server (xcb_conn); ++ ++ /* Some drivers (nvidia I look at you!) might no advertise some CRTCs, so in ++ * such case, we may ignore X errors here */ ++ xcb_cookie = xcb_randr_set_screen_size_checked (xcb_conn, ++ DefaultRootWindow (manager_xrandr->xdisplay), ++ width, height, ++ width_mm, height_mm); ++ xcb_error = xcb_request_check (xcb_conn, xcb_cookie); ++ if (!xcb_error) ++ { ++ manager->screen_width = width; ++ manager->screen_height = height; ++ } ++ else ++ { ++ gchar buf[64]; ++ ++ XGetErrorText (manager_xrandr->xdisplay, xcb_error->error_code, buf, ++ sizeof (buf) - 1); ++ g_warning ("Impossible to resize screen at size %dx%d, error id %u: %s", ++ width, height, xcb_error->error_code, buf); ++ g_clear_pointer (&xcb_error, free); ++ } + -+ manager->screen_width = width; -+ manager->screen_height = height; ++ xcb_ungrab_server (xcb_conn); +} + static xcb_randr_rotation_t meta_monitor_transform_to_xrandr (MetaMonitorTransform transform) { -@@ -240,21 +295,89 @@ xrandr_set_crtc_config (MetaMonitorManagerXrandr *manager_xrandr, +@@ -240,13 +318,50 @@ xrandr_set_crtc_config (MetaMonitorManagerXrandr *manager_xrandr, return TRUE; } @@ -2108,19 +2577,32 @@ +is_crtc_assignment_changed (MetaMonitorManager *monitor_manager, + MetaCrtc *crtc, + MetaCrtcInfo **crtc_infos, -+ unsigned int n_crtc_infos) ++ unsigned int n_crtc_infos, ++ gboolean *weak_change) { ++ MetaLogicalMonitorLayoutMode layout_mode; + gboolean have_scaling; ++ float max_crtc_scale = 1.0f; ++ float max_req_scale = 1.0f; unsigned int i; ++ layout_mode = meta_monitor_manager_get_default_layout_mode (monitor_manager); + have_scaling = meta_monitor_manager_get_capabilities (monitor_manager) & + META_MONITOR_MANAGER_CAPABILITY_NATIVE_OUTPUT_SCALING; + ++ if (have_scaling && ++ layout_mode == META_LOGICAL_MONITOR_LAYOUT_MODE_GLOBAL_UI_LOGICAL) ++ { ++ max_crtc_scale = ++ meta_monitor_manager_get_maximum_crtc_scale (monitor_manager); ++ max_req_scale = ++ get_maximum_crtc_info_scale (crtc_infos, n_crtc_infos); ++ } ++ for (i = 0; i < n_crtc_infos; i++) { -+ unsigned int j; MetaCrtcInfo *crtc_info = crtc_infos[i]; - +@@ -254,7 +369,42 @@ is_crtc_assignment_changed (MetaCrtc *crtc, if (crtc_info->crtc != crtc) continue; @@ -2132,16 +2614,17 @@ + { + float crtc_scale = crtc->scale; + float req_output_scale = crtc_info->scale; -+ MetaLogicalMonitorLayoutMode layout_mode = -+ meta_monitor_manager_get_default_layout_mode (monitor_manager); + -+ if (layout_mode == META_LOGICAL_MONITOR_LAYOUT_MODE_GLOBAL_UI_LOGICAL) ++ if (layout_mode == META_LOGICAL_MONITOR_LAYOUT_MODE_PHYSICAL) ++ { ++ if (fmodf (crtc_scale, 1.0) == 0.0f) ++ { ++ *weak_change = fabsf (crtc_scale - req_output_scale) > 0.001; ++ return FALSE; ++ } ++ } ++ else if (layout_mode == META_LOGICAL_MONITOR_LAYOUT_MODE_GLOBAL_UI_LOGICAL) + { -+ float max_crtc_scale = -+ meta_monitor_manager_get_maximum_crtc_scale (monitor_manager); -+ float max_req_scale = -+ get_maximum_crtc_info_scale (crtc_infos, n_crtc_infos); -+ + /* In scale ui-down mode we need to check if the actual output + * scale that will be applied to the crtc has actually changed + * from the current value, so we need to compare the current crtc @@ -2155,17 +2638,7 @@ + req_output_scale /= ceilf (max_req_scale); + } + -+ if (fabs (crtc_scale - req_output_scale) > 0.001) -+ return TRUE; -+ } -+ -+ for (j = 0; j < crtc_info->outputs->len; j++) -+ { -+ MetaOutput *output = ((MetaOutput**) crtc_info->outputs->pdata)[j]; -+ MetaCrtc *assigned_crtc; -+ -+ assigned_crtc = meta_output_get_assigned_crtc (output); -+ if (assigned_crtc != crtc) ++ if (fabsf (crtc_scale - req_output_scale) > 0.001) + return TRUE; + } + @@ -2173,16 +2646,26 @@ } return !!meta_crtc_xrandr_get_current_mode (crtc); -@@ -339,7 +462,7 @@ is_assignments_changed (MetaMonitorManager *manager, +@@ -328,7 +478,8 @@ is_assignments_changed (MetaMonitorManager *manager, + MetaCrtcInfo **crtc_infos, + unsigned int n_crtc_infos, + MetaOutputInfo **output_infos, +- unsigned int n_output_infos) ++ unsigned int n_output_infos, ++ gboolean *weak_change) + { + MetaMonitorManagerXrandr *manager_xrandr = + META_MONITOR_MANAGER_XRANDR (manager); +@@ -339,7 +490,7 @@ is_assignments_changed (MetaMonitorManager *manager, { MetaCrtc *crtc = l->data; - if (is_crtc_assignment_changed (crtc, crtc_infos, n_crtc_infos)) -+ if (is_crtc_assignment_changed (manager, crtc, crtc_infos, n_crtc_infos)) ++ if (is_crtc_assignment_changed (manager, crtc, crtc_infos, n_crtc_infos, weak_change)) return TRUE; } -@@ -355,6 +478,32 @@ is_assignments_changed (MetaMonitorManager *manager, +@@ -355,6 +506,32 @@ is_assignments_changed (MetaMonitorManager *manager, return TRUE; } @@ -2215,7 +2698,7 @@ return FALSE; } -@@ -368,27 +517,57 @@ apply_crtc_assignments (MetaMonitorManager *manager, +@@ -368,27 +545,47 @@ apply_crtc_assignments (MetaMonitorManager *manager, { MetaMonitorManagerXrandr *manager_xrandr = META_MONITOR_MANAGER_XRANDR (manager); MetaGpu *gpu = meta_monitor_manager_xrandr_get_gpu (manager_xrandr); @@ -2253,34 +2736,22 @@ if (crtc_info->mode == NULL) continue; -- width = MAX (width, (int) roundf (crtc_info->layout.origin.x + -- crtc_info->layout.size.width)); -- height = MAX (height, (int) roundf (crtc_info->layout.origin.y + -- crtc_info->layout.size.height)); + if (have_scaling && scale_mode == META_X11_SCALE_MODE_UI_DOWN) -+ scale = ceilf (max_scale) / crtc_info->scale; ++ scale = (ceilf (max_scale) / crtc_info->scale) * crtc_info->scale; + -+ if (meta_monitor_transform_is_rotated (crtc_info->transform)) -+ { -+ width = MAX (width, crtc_info->layout.origin.x + -+ roundf (crtc_info->layout.size.height * scale)); -+ height = MAX (height, crtc_info->layout.origin.y + -+ roundf (crtc_info->layout.size.width * scale)); -+ } -+ else -+ { -+ width = MAX (width, crtc_info->layout.origin.x + -+ roundf (crtc_info->layout.size.width * scale)); -+ height = MAX (height, crtc_info->layout.origin.y + -+ roundf (crtc_info->layout.size.height * scale)); -+ } + width = MAX (width, (int) roundf (crtc_info->layout.origin.x + +- crtc_info->layout.size.width)); ++ crtc_info->layout.size.width * scale)); + height = MAX (height, (int) roundf (crtc_info->layout.origin.y + +- crtc_info->layout.size.height)); ++ crtc_info->layout.size.height * scale)); + + avg_screen_scale += (crtc_info->scale - avg_screen_scale) / + (float) (++valid_crtcs); } /* Second disable all newly disabled CRTCs, or CRTCs that in the previous -@@ -422,6 +601,9 @@ apply_crtc_assignments (MetaMonitorManager *manager, +@@ -422,8 +619,12 @@ apply_crtc_assignments (MetaMonitorManager *manager, 0, 0, XCB_NONE, XCB_RANDR_ROTATION_ROTATE_0, NULL, 0); @@ -2289,18 +2760,25 @@ + (xcb_randr_crtc_t) crtc->crtc_id, 1.0f); meta_crtc_unset_config (crtc); ++ crtc->scale = 1.0f; } -@@ -449,21 +631,15 @@ apply_crtc_assignments (MetaMonitorManager *manager, + } + +@@ -449,24 +650,23 @@ apply_crtc_assignments (MetaMonitorManager *manager, 0, 0, XCB_NONE, XCB_RANDR_ROTATION_ROTATE_0, NULL, 0); + if (have_scaling) -+ meta_crtc_xrandr_set_scale (crtc, -+ (xcb_randr_crtc_t) crtc->crtc_id, 1.0f); ++ meta_crtc_xrandr_set_scale (crtc, ++ (xcb_randr_crtc_t) crtc->crtc_id, 1.0f); meta_crtc_unset_config (crtc); ++ crtc->scale = 1.0f; } + if (!n_crtcs) + goto out; + - g_assert (width > 0 && height > 0); - /* The 'physical size' of an X screen is meaningless if that screen - * can consist of many monitors. So just pick a size that make the @@ -2312,12 +2790,16 @@ - height_mm = (height / DPI_FALLBACK) * 25.4 + 0.5; - XRRSetScreenSize (manager_xrandr->xdisplay, DefaultRootWindow (manager_xrandr->xdisplay), - width, height, width_mm, height_mm); -+ meta_monitor_manager_xrandr_update_screen_size (manager_xrandr, width, height, -+ avg_screen_scale); ++ if (width > manager->screen_width || height > manager->screen_height) ++ { ++ meta_monitor_manager_xrandr_update_screen_size (manager_xrandr, ++ width, height, ++ avg_screen_scale); ++ } for (i = 0; i < n_crtcs; i++) { -@@ -476,12 +652,21 @@ apply_crtc_assignments (MetaMonitorManager *manager, +@@ -479,12 +679,21 @@ apply_crtc_assignments (MetaMonitorManager *manager, g_autofree xcb_randr_output_t *output_ids = NULL; unsigned int j, n_output_ids; xcb_randr_rotation_t rotation; @@ -2328,7 +2810,7 @@ n_output_ids = crtc_info->outputs->len; output_ids = g_new (xcb_randr_output_t, n_output_ids); -+ if (have_scaling) ++ if (have_scaling && scale_mode != META_X11_SCALE_MODE_NONE) + { + scale = crtc_info->scale; + @@ -2339,7 +2821,7 @@ for (j = 0; j < n_output_ids; j++) { MetaOutput *output; -@@ -494,6 +679,20 @@ apply_crtc_assignments (MetaMonitorManager *manager, +@@ -497,6 +706,17 @@ apply_crtc_assignments (MetaMonitorManager *manager, output_ids[j] = output->winsys_id; } @@ -2349,26 +2831,47 @@ + (xcb_randr_crtc_t) crtc->crtc_id, + scale)) + { -+ scale = 1.0f; + meta_warning ("Scalig CRTC %d at %f failed\n", + (unsigned)crtc->crtc_id, scale); + } -+ else if (scale_mode == META_X11_SCALE_MODE_UI_DOWN) -+ scale = crtc_info->scale; + } + rotation = meta_monitor_transform_to_xrandr (crtc_info->transform); if (!xrandr_set_crtc_config (manager_xrandr, crtc, -@@ -519,6 +718,7 @@ apply_crtc_assignments (MetaMonitorManager *manager, +@@ -522,6 +742,17 @@ apply_crtc_assignments (MetaMonitorManager *manager, &crtc_info->layout, mode, crtc_info->transform); -+ crtc->scale = scale; ++ crtc->scale = crtc_info->scale; ++ ++ if (have_scaling && scale_mode == META_X11_SCALE_MODE_UI_DOWN) ++ { ++ scale = (ceilf (max_scale) / crtc_info->scale) * crtc_info->scale; ++ ++ crtc->config->layout.size.width = ++ roundf (crtc->config->layout.size.width * scale); ++ crtc->config->layout.size.height = ++ roundf (crtc->config->layout.size.height * scale); ++ } } } -@@ -574,14 +774,63 @@ meta_monitor_manager_xrandr_ensure_initial_config (MetaMonitorManager *manager) +@@ -552,6 +783,13 @@ apply_crtc_assignments (MetaMonitorManager *manager, + output->is_primary = FALSE; + } + ++ if (width > 0 && height > 0) ++ { ++ meta_monitor_manager_xrandr_update_screen_size (manager_xrandr, ++ width, height, ++ avg_screen_scale); ++ } ++ + out: + XUngrabServer (manager_xrandr->xdisplay); + XFlush (manager_xrandr->xdisplay); +@@ -578,14 +816,82 @@ meta_monitor_manager_xrandr_ensure_initial_config (MetaMonitorManager *manager) } static void @@ -2379,7 +2882,6 @@ { MetaMonitorManagerXrandr *manager_xrandr = META_MONITOR_MANAGER_XRANDR (manager); -+ MetaGpu *gpu = meta_monitor_manager_xrandr_get_gpu (manager_xrandr); + MetaBackend *backend = meta_monitor_manager_get_backend (manager); + MetaSettings *settings = meta_backend_get_settings (backend); + MetaX11ScaleMode scale_mode = meta_settings_get_x11_scale_mode (settings); @@ -2394,13 +2896,15 @@ + META_MONITOR_MANAGER_CAPABILITY_NATIVE_OUTPUT_SCALING; + + /* Compute the new size of the screen (framebuffer) */ -+ for (l = meta_gpu_get_crtcs (gpu); l; l = l->next) ++ for (l = manager->monitors; l != NULL; l = l->next) + { ++ MetaMonitor *monitor = l->data; ++ MetaOutput *output = meta_monitor_get_main_output (monitor); ++ MetaCrtc *crtc = meta_output_get_assigned_crtc (output); ++ graphene_rect_t *crtc_layout; + float scale = 1.0f; -+ MetaCrtc *crtc = l->data; -+ MetaCrtcConfig *crtc_config = crtc->config; + -+ if (crtc_config == NULL) ++ if (!crtc || !crtc->config) + continue; + + if (!have_scaling || scale_mode != META_X11_SCALE_MODE_UI_DOWN) @@ -2414,10 +2918,11 @@ + /* When computing the screen size from the crtc rects we don't have to + * use inverted values when monitors are rotated, because this is already + * taken in account in the crtc rectangles */ -+ screen_width = MAX (screen_width, crtc_config->layout.origin.x + -+ roundf (crtc_config->layout.size.width * scale)); -+ screen_height = MAX (screen_height, crtc_config->layout.origin.y + -+ roundf (crtc_config->layout.size.height * scale)); ++ crtc_layout = &crtc->config->layout; ++ screen_width = MAX (screen_width, crtc_layout->origin.x + ++ roundf (crtc_layout->size.width * scale)); ++ screen_height = MAX (screen_height, crtc_layout->origin.y + ++ roundf (crtc_layout->size.height * scale)); + ++n_crtcs; + + /* This value isn't completely exact, since it doesn't take care of the @@ -2430,50 +2935,83 @@ - g_clear_pointer (&manager_xrandr->supported_scales, g_free); - meta_monitor_manager_rebuild_derived (manager, config); + if (screen_width > 0 && screen_height > 0) -+ meta_monitor_manager_xrandr_update_screen_size (manager_xrandr, -+ screen_width, screen_height, -+ average_scale); ++ { ++ meta_monitor_manager_xrandr_update_screen_size (manager_xrandr, ++ screen_width, ++ screen_height, ++ average_scale); ++ } ++} ++ ++static void ++maybe_update_ui_scaling_factor (MetaMonitorManager *manager, ++ MetaMonitorsConfig *config) ++{ ++ if (config->layout_mode == META_LOGICAL_MONITOR_LAYOUT_MODE_GLOBAL_UI_LOGICAL || ++ manager->layout_mode == META_LOGICAL_MONITOR_LAYOUT_MODE_GLOBAL_UI_LOGICAL) ++ { ++ MetaBackend *backend = meta_monitor_manager_get_backend (manager); ++ MetaSettings *settings = meta_backend_get_settings (backend); ++ ++ meta_settings_update_ui_scaling_factor (settings); ++ } } static gboolean -@@ -595,7 +844,7 @@ meta_monitor_manager_xrandr_apply_monitors_config (MetaMonitorManager *mana +@@ -602,7 +908,7 @@ meta_monitor_manager_xrandr_apply_monitors_config (MetaMonitorManager *mana + if (!manager->in_init) + apply_crtc_assignments (manager, TRUE, NULL, 0, NULL, 0); - if (!config) - { - meta_monitor_manager_xrandr_rebuild_derived (manager, NULL); + meta_monitor_manager_rebuild_derived (manager, NULL); return TRUE; } -@@ -620,16 +869,26 @@ meta_monitor_manager_xrandr_apply_monitors_config (MetaMonitorManager *mana +@@ -613,6 +919,8 @@ meta_monitor_manager_xrandr_apply_monitors_config (MetaMonitorManager *mana + + if (method != META_MONITORS_CONFIG_METHOD_VERIFY) + { ++ gboolean weak_change = FALSE; ++ + /* + * If the assignment has not changed, we won't get any notification about + * any new configuration from the X server; but we still need to update +@@ -620,12 +928,16 @@ meta_monitor_manager_xrandr_apply_monitors_config (MetaMonitorManager *mana + * have changed locally, such as the logical monitors scale. This means we + * must check that our new assignment actually changes anything, otherwise + * just update the logical state. ++ * If we record a weak change it means that only UI scaling needs to be ++ * updated and so that we don't have to reconfigure the CRTCs, but still ++ * need to update the logical state. + */ + if (is_assignments_changed (manager, + (MetaCrtcInfo **) crtc_infos->pdata, + crtc_infos->len, (MetaOutputInfo **) output_infos->pdata, - output_infos->len)) +- output_infos->len)) ++ output_infos->len, ++ &weak_change)) { -+ MetaLogicalMonitorLayoutMode layout_mode = -+ meta_monitor_manager_get_default_layout_mode (manager); -+ apply_crtc_assignments (manager, TRUE, - (MetaCrtcInfo **) crtc_infos->pdata, +@@ -633,10 +945,15 @@ meta_monitor_manager_xrandr_apply_monitors_config (MetaMonitorManager *mana crtc_infos->len, (MetaOutputInfo **) output_infos->pdata, output_infos->len); + -+ if (layout_mode == META_LOGICAL_MONITOR_LAYOUT_MODE_GLOBAL_UI_LOGICAL) -+ { -+ MetaBackend *backend = meta_monitor_manager_get_backend (manager); -+ MetaSettings *settings = meta_backend_get_settings (backend); -+ meta_settings_update_ui_scaling_factor (settings); -+ } ++ maybe_update_ui_scaling_factor (manager, config); } else { - meta_monitor_manager_xrandr_rebuild_derived (manager, config); ++ if (weak_change) ++ maybe_update_ui_scaling_factor (manager, config); ++ + meta_monitor_manager_rebuild_derived (manager, config); } } -@@ -759,7 +1018,8 @@ meta_monitor_manager_xrandr_tiled_monitor_added (MetaMonitorManager *manager, +@@ -766,7 +1083,8 @@ meta_monitor_manager_xrandr_tiled_monitor_added (MetaMonitorManager *manager, GList *l; int i; @@ -2483,7 +3021,7 @@ return; product = meta_monitor_get_product (monitor); -@@ -808,7 +1068,8 @@ meta_monitor_manager_xrandr_tiled_monitor_removed (MetaMonitorManager *manager, +@@ -815,7 +1133,8 @@ meta_monitor_manager_xrandr_tiled_monitor_removed (MetaMonitorManager *manager, int monitor_count; @@ -2493,7 +3031,7 @@ return; monitor_xrandr_data = meta_monitor_xrandr_data_from_monitor (monitor); -@@ -826,10 +1087,12 @@ meta_monitor_manager_xrandr_tiled_monitor_removed (MetaMonitorManager *manager, +@@ -833,10 +1152,12 @@ meta_monitor_manager_xrandr_tiled_monitor_removed (MetaMonitorManager *manager, static void meta_monitor_manager_xrandr_init_monitors (MetaMonitorManagerXrandr *manager_xrandr) { @@ -2507,7 +3045,7 @@ return; /* delete any tiled monitors setup, as mutter will want to recreate -@@ -860,83 +1123,26 @@ meta_monitor_manager_xrandr_is_transform_handled (MetaMonitorManager *manager, +@@ -867,83 +1188,26 @@ meta_monitor_manager_xrandr_is_transform_handled (MetaMonitorManager *manager, return TRUE; } @@ -2515,34 +3053,33 @@ -meta_monitor_manager_xrandr_calculate_monitor_mode_scale (MetaMonitorManager *manager, - MetaMonitor *monitor, - MetaMonitorMode *monitor_mode) --{ ++static MetaMonitorScalesConstraint ++get_scale_constraints (MetaMonitorManager *manager) + { - return meta_monitor_calculate_mode_scale (monitor, monitor_mode); -} -- ++ MetaMonitorScalesConstraint constraints = 0; + -static void -add_supported_scale (GArray *supported_scales, - float scale) -+static MetaMonitorScalesConstraint -+get_scale_constraints (MetaMonitorManager *manager) - { +-{ - unsigned int i; -+ MetaMonitorScalesConstraint constraints = 0; - -- for (i = 0; i < supported_scales->len; i++) -- { -- float supported_scale = g_array_index (supported_scales, float, i); + if (meta_monitor_manager_get_capabilities (manager) & + META_MONITOR_MANAGER_CAPABILITY_GLOBAL_SCALE_REQUIRED) + constraints |= META_MONITOR_SCALES_CONSTRAINT_NO_FRAC; +- for (i = 0; i < supported_scales->len; i++) +- { +- float supported_scale = g_array_index (supported_scales, float, i); +- - if (scale == supported_scale) - return; - } - - g_array_append_val (supported_scales, scale); -+ return constraints; - } - +-} +- -static int -compare_scales (gconstpointer a, - gconstpointer b) @@ -2554,8 +3091,9 @@ - if (f > 0) - return 1; - return 0; --} -- ++ return constraints; + } + -static void -ensure_supported_monitor_scales (MetaMonitorManager *manager) +static float @@ -2605,7 +3143,7 @@ } static float * -@@ -946,20 +1152,35 @@ meta_monitor_manager_xrandr_calculate_supported_scales (MetaMonitorManager +@@ -953,20 +1217,38 @@ meta_monitor_manager_xrandr_calculate_supported_scales (MetaMonitorManager MetaMonitorMode *monitor_mode, int *n_supported_scales) { @@ -2631,15 +3169,18 @@ + MetaBackend *backend = meta_monitor_manager_get_backend (manager); + MetaSettings *settings = meta_backend_get_settings (backend); + ++ capabilities = META_MONITOR_MANAGER_CAPABILITY_NONE; ++ + if (xrandr_manager->randr_version >= RANDR_TILING_MIN_VERSION) + capabilities |= META_MONITOR_MANAGER_CAPABILITY_TILING; + ++ if (xrandr_manager->randr_version >= RANDR_TRANSFORM_MIN_VERSION) ++ capabilities |= META_MONITOR_MANAGER_CAPABILITY_NATIVE_OUTPUT_SCALING; ++ + if (meta_settings_is_experimental_feature_enabled (settings, -+ META_EXPERIMENTAL_FEATURE_X11_RANDR_FRACTIONAL_SCALING) && -+ xrandr_manager->randr_version >= RANDR_TRANSFORM_MIN_VERSION) ++ META_EXPERIMENTAL_FEATURE_X11_RANDR_FRACTIONAL_SCALING)) + { -+ capabilities |= META_MONITOR_MANAGER_CAPABILITY_NATIVE_OUTPUT_SCALING | -+ META_MONITOR_MANAGER_CAPABILITY_LAYOUT_MODE; ++ capabilities |= META_MONITOR_MANAGER_CAPABILITY_LAYOUT_MODE; + } + else + { @@ -2650,7 +3191,7 @@ } static gboolean -@@ -977,9 +1198,34 @@ meta_monitor_manager_xrandr_get_max_screen_size (MetaMonitorManager *manager, +@@ -984,9 +1266,41 @@ meta_monitor_manager_xrandr_get_max_screen_size (MetaMonitorManager *manager, return TRUE; } @@ -2658,10 +3199,14 @@ +scale_mode_changed (MetaSettings *settings, + MetaMonitorManager *manager) +{ -+ if (!(meta_monitor_manager_get_capabilities(manager) & ++ if (!(meta_monitor_manager_get_capabilities (manager) & + META_MONITOR_MANAGER_CAPABILITY_NATIVE_OUTPUT_SCALING)) + return; + ++ if (!meta_settings_is_experimental_feature_enabled (settings, ++ META_EXPERIMENTAL_FEATURE_X11_RANDR_FRACTIONAL_SCALING)) ++ return; ++ + meta_monitor_manager_on_hotplug (manager); + meta_settings_update_ui_scaling_factor (settings); +} @@ -2669,8 +3214,11 @@ static MetaLogicalMonitorLayoutMode meta_monitor_manager_xrandr_get_default_layout_mode (MetaMonitorManager *manager) { -+ if (meta_monitor_manager_get_capabilities (manager) & -+ META_MONITOR_MANAGER_CAPABILITY_NATIVE_OUTPUT_SCALING) ++ MetaMonitorManagerCapability capabilities = ++ meta_monitor_manager_get_capabilities (manager); ++ ++ if ((capabilities & META_MONITOR_MANAGER_CAPABILITY_NATIVE_OUTPUT_SCALING) && ++ (capabilities & META_MONITOR_MANAGER_CAPABILITY_LAYOUT_MODE)) + { + MetaBackend *backend = meta_monitor_manager_get_backend (manager); + MetaSettings *settings = meta_backend_get_settings (backend); @@ -2678,14 +3226,14 @@ + + if (scale_mode == META_X11_SCALE_MODE_UI_DOWN) + return META_LOGICAL_MONITOR_LAYOUT_MODE_GLOBAL_UI_LOGICAL; -+ -+ return META_LOGICAL_MONITOR_LAYOUT_MODE_LOGICAL; ++ else if (scale_mode == META_X11_SCALE_MODE_UP) ++ return META_LOGICAL_MONITOR_LAYOUT_MODE_LOGICAL; + } + return META_LOGICAL_MONITOR_LAYOUT_MODE_PHYSICAL; } -@@ -991,6 +1237,7 @@ meta_monitor_manager_xrandr_constructed (GObject *object) +@@ -998,6 +1312,7 @@ meta_monitor_manager_xrandr_constructed (GObject *object) MetaMonitorManager *manager = META_MONITOR_MANAGER (manager_xrandr); MetaBackend *backend = meta_monitor_manager_get_backend (manager); MetaBackendX11 *backend_x11 = META_BACKEND_X11 (backend); @@ -2693,7 +3241,7 @@ manager_xrandr->xdisplay = meta_backend_x11_get_xdisplay (backend_x11); -@@ -1011,19 +1258,19 @@ meta_monitor_manager_xrandr_constructed (GObject *object) +@@ -1018,19 +1333,19 @@ meta_monitor_manager_xrandr_constructed (GObject *object) | RRCrtcChangeNotifyMask | RROutputPropertyNotifyMask); @@ -2721,7 +3269,7 @@ G_OBJECT_CLASS (meta_monitor_manager_xrandr_parent_class)->constructed (object); } -@@ -1033,7 +1280,6 @@ meta_monitor_manager_xrandr_finalize (GObject *object) +@@ -1040,7 +1355,6 @@ meta_monitor_manager_xrandr_finalize (GObject *object) MetaMonitorManagerXrandr *manager_xrandr = META_MONITOR_MANAGER_XRANDR (object); g_hash_table_destroy (manager_xrandr->tiled_monitor_atoms); @@ -2729,7 +3277,7 @@ G_OBJECT_CLASS (meta_monitor_manager_xrandr_parent_class)->finalize (object); } -@@ -1056,6 +1302,7 @@ meta_monitor_manager_xrandr_class_init (MetaMonitorManagerXrandrClass *klass) +@@ -1063,6 +1377,7 @@ meta_monitor_manager_xrandr_class_init (MetaMonitorManagerXrandrClass *klass) manager_class->read_current_state = meta_monitor_manager_xrandr_read_current_state; manager_class->ensure_initial_config = meta_monitor_manager_xrandr_ensure_initial_config; manager_class->apply_monitors_config = meta_monitor_manager_xrandr_apply_monitors_config; @@ -2737,7 +3285,7 @@ manager_class->set_power_save_mode = meta_monitor_manager_xrandr_set_power_save_mode; manager_class->change_backlight = meta_monitor_manager_xrandr_change_backlight; manager_class->get_crtc_gamma = meta_monitor_manager_xrandr_get_crtc_gamma; -@@ -1117,7 +1364,7 @@ meta_monitor_manager_xrandr_handle_xevent (MetaMonitorManagerXrandr *manager_xra +@@ -1124,7 +1439,7 @@ meta_monitor_manager_xrandr_handle_xevent (MetaMonitorManagerXrandr *manager_xra config = NULL; } @@ -2786,7 +3334,7 @@ tile_atom = XInternAtom (xdisplay, "TILE", FALSE); diff --git a/src/compositor/meta-compositor-x11.c b/src/compositor/meta-compositor-x11.c -index 1737e97..755e733 100644 +index ba9cca2..4043d81 100644 --- a/src/compositor/meta-compositor-x11.c +++ b/src/compositor/meta-compositor-x11.c @@ -31,6 +31,7 @@ @@ -2797,15 +3345,16 @@ #include "x11/meta-x11-display-private.h" struct _MetaCompositorX11 -@@ -43,6 +44,7 @@ struct _MetaCompositorX11 - gboolean have_x11_sync_object; - - MetaWindow *unredirected_window; +@@ -47,6 +48,8 @@ struct _MetaCompositorX11 + gboolean xserver_uses_monotonic_clock; + int64_t xserver_time_query_time_us; + int64_t xserver_time_offset_us; ++ + gboolean randr_scale_disabled; }; G_DEFINE_TYPE (MetaCompositorX11, meta_compositor_x11, META_TYPE_COMPOSITOR) -@@ -206,20 +208,91 @@ shape_cow_for_window (MetaCompositorX11 *compositor_x11, +@@ -238,20 +241,91 @@ shape_cow_for_window (MetaCompositorX11 *compositor_x11, } } @@ -2898,7 +3447,7 @@ window_actor = meta_window_actor_from_window (prev_unredirected_window); window_actor_x11 = META_WINDOW_ACTOR_X11 (window_actor); meta_window_actor_x11_set_unredirected (window_actor_x11, FALSE); -@@ -233,6 +306,17 @@ set_unredirected_window (MetaCompositorX11 *compositor_x11, +@@ -265,6 +339,17 @@ set_unredirected_window (MetaCompositorX11 *compositor_x11, MetaWindowActor *window_actor; MetaWindowActorX11 *window_actor_x11; @@ -2916,7 +3465,7 @@ window_actor = meta_window_actor_from_window (window); window_actor_x11 = META_WINDOW_ACTOR_X11 (window_actor); meta_window_actor_x11_set_unredirected (window_actor_x11, TRUE); -@@ -244,21 +328,11 @@ maybe_unredirect_top_window (MetaCompositorX11 *compositor_x11) +@@ -276,21 +361,11 @@ maybe_unredirect_top_window (MetaCompositorX11 *compositor_x11) { MetaCompositor *compositor = META_COMPOSITOR (compositor_x11); MetaWindow *window_to_unredirect = NULL; @@ -2986,262 +3535,8 @@ void meta_rectangle_clamp_to_fit_into_region (const GList *spanning_rects, -diff --git a/src/core/meta-selection-source-memory-pool-private.h b/src/core/meta-selection-source-memory-pool-private.h -new file mode 100644 -index 0000000..a02d484 ---- /dev/null -+++ b/src/core/meta-selection-source-memory-pool-private.h -@@ -0,0 +1,47 @@ -+/* -+ * Copyright (C) 2019 Canonical Ltd. -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License as -+ * published by the Free Software Foundation; either version 2 of the -+ * License, or (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA -+ * 02111-1307, USA. -+ * -+ * Author: Marco Trevisan -+ */ -+ -+#ifndef META_MEMORY_POOL_SELECTION_SOURCE_H -+#define META_MEMORY_POOL_SELECTION_SOURCE_H -+ -+#include "meta/meta-selection-source.h" -+#include "meta/meta-selection-source-memory.h" -+ -+#define META_TYPE_SELECTION_SOURCE_MEMORY_POOL (meta_selection_source_memory_pool_get_type ()) -+ -+G_DECLARE_FINAL_TYPE (MetaSelectionSourceMemoryPool, -+ meta_selection_source_memory_pool, -+ META, SELECTION_SOURCE_MEMORY_POOL, -+ MetaSelectionSource) -+ -+MetaSelectionSource * meta_selection_source_memory_pool_new (void); -+ -+void meta_selection_source_memory_pool_add (MetaSelectionSourceMemoryPool *pool, -+ MetaSelectionSourceMemory *source); -+ -+void meta_selection_source_memory_pool_remove (MetaSelectionSourceMemoryPool *pool, -+ MetaSelectionSourceMemory *source); -+ -+void meta_selection_source_memory_pool_clear (MetaSelectionSourceMemoryPool *pool); -+ -+gboolean meta_selection_source_memory_pool_has_sources (MetaSelectionSourceMemoryPool *pool); -+ -+#endif /* META_MEMORY_POOL_SELECTION_SOURCE_H */ -diff --git a/src/core/meta-selection-source-memory-pool.c b/src/core/meta-selection-source-memory-pool.c -new file mode 100644 -index 0000000..32d806e ---- /dev/null -+++ b/src/core/meta-selection-source-memory-pool.c -@@ -0,0 +1,195 @@ -+/* -+ * Copyright (C) 2019 Canonical Ltd. -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License as -+ * published by the Free Software Foundation; either version 2 of the -+ * License, or (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA -+ * 02111-1307, USA. -+ * -+ * Author: Marco Trevisan -+ */ -+ -+#include "config.h" -+ -+#include "meta-selection-source-memory-pool-private.h" -+#include "meta/meta-selection-source.h" -+ -+struct _MetaSelectionSourceMemoryPool -+{ -+ MetaSelectionSource parent_instance; -+ GList *sources; -+}; -+ -+G_DEFINE_TYPE (MetaSelectionSourceMemoryPool, -+ meta_selection_source_memory_pool, -+ META_TYPE_SELECTION_SOURCE) -+ -+static void -+meta_selection_source_memory_pool_read_async (MetaSelectionSource *source, -+ const char *mimetype, -+ GCancellable *cancellable, -+ GAsyncReadyCallback callback, -+ gpointer user_data) -+{ -+ MetaSelectionSourceMemoryPool *pool = -+ META_SELECTION_SOURCE_MEMORY_POOL (source); -+ MetaSelectionSource *pool_source = NULL; -+ GTask *task; -+ GList *l; -+ // gboolean has_mimetype; -+ -+ // has_mimetype = FALSE; -+ -+ for (l = pool->sources; l; l = l->next) -+ { -+ GList *mimetypes = meta_selection_source_get_mimetypes (l->data); -+ -+ if (g_list_find_custom (mimetypes, mimetype, (GCompareFunc) g_strcmp0)) -+ pool_source = l->data; -+ -+ g_list_free_full (mimetypes, g_free); -+ -+ if (pool_source) -+ break; -+ } -+ -+ if (!pool_source) -+ { -+ g_task_report_new_error (source, callback, user_data, -+ meta_selection_source_memory_pool_read_async, -+ G_IO_ERROR, G_IO_ERROR_FAILED, -+ "Mimetype %s not in selection", -+ mimetype); -+ return; -+ } -+ -+ // source = l->data; -+ // task = g_task_new (source, cancellable, callback, user_data); -+ // g_task_set_source_tag (task, meta_selection_source_memory_pool_read_async); -+ -+ meta_selection_source_read_async (pool_source, mimetype, cancellable, -+ callback, user_data); -+} -+ -+static GInputStream * -+meta_selection_source_memory_pool_read_finish (MetaSelectionSource *source, -+ GAsyncResult *result, -+ GError **error) -+{ -+ // g_assert (g_task_get_source_tag (G_TASK (result)) == -+ // meta_selection_source_memory_pool_read_async); -+ g_print("FINISH READING FROM MEMORY POOOL\n"); -+ return g_task_propagate_pointer (G_TASK (result), error); -+} -+ -+static GList * -+meta_selection_source_memory_pool_get_mimetypes (MetaSelectionSource *source) -+{ -+ MetaSelectionSourceMemoryPool *pool = -+ META_SELECTION_SOURCE_MEMORY_POOL (source); -+ GList *sources = NULL; -+ GList *l; -+ -+ if (!pool->sources) -+ return NULL; -+ -+ for (l = pool->sources; l; l = l->next) -+ { -+ GList *mimetypes; -+ -+ mimetypes = meta_selection_source_get_mimetypes (l->data); -+ sources = g_list_concat (sources, mimetypes); -+ } -+ -+ return sources; -+} -+ -+static void -+meta_selection_source_memory_pool_finalize (GObject *object) -+{ -+ MetaSelectionSourceMemoryPool *pool = -+ META_SELECTION_SOURCE_MEMORY_POOL (object); -+ -+ g_list_free_full (pool->sources, g_object_unref); -+ -+ G_OBJECT_CLASS (meta_selection_source_memory_pool_parent_class)->finalize (object); -+} -+ -+static void -+meta_selection_source_memory_pool_class_init (MetaSelectionSourceMemoryPoolClass *klass) -+{ -+ MetaSelectionSourceClass *source_class = META_SELECTION_SOURCE_CLASS (klass); -+ GObjectClass *object_class = G_OBJECT_CLASS (klass); -+ -+ object_class->finalize = meta_selection_source_memory_pool_finalize; -+ -+ source_class->read_async = meta_selection_source_memory_pool_read_async; -+ source_class->read_finish = meta_selection_source_memory_pool_read_finish; -+ source_class->get_mimetypes = meta_selection_source_memory_pool_get_mimetypes; -+} -+ -+static void -+meta_selection_source_memory_pool_init (MetaSelectionSourceMemoryPool *source) -+{ -+} -+ -+MetaSelectionSource * -+meta_selection_source_memory_pool_new (void) -+{ -+ MetaSelectionSourceMemoryPool *pool; -+ -+ pool = g_object_new (META_TYPE_SELECTION_SOURCE_MEMORY_POOL, NULL); -+ -+ return META_SELECTION_SOURCE (pool); -+} -+ -+void -+meta_selection_source_memory_pool_add (MetaSelectionSourceMemoryPool *pool, -+ MetaSelectionSourceMemory *source) -+{ -+ g_return_if_fail (META_IS_SELECTION_SOURCE_MEMORY_POOL (pool)); -+ g_return_if_fail (META_IS_SELECTION_SOURCE_MEMORY (source)); -+ g_return_if_fail (g_list_find (pool->sources, source) == NULL); -+ -+ pool->sources = g_list_prepend (pool->sources, g_object_ref (source)); -+} -+ -+void -+meta_selection_source_memory_pool_remove (MetaSelectionSourceMemoryPool *pool, -+ MetaSelectionSourceMemory *source) -+{ -+ g_return_if_fail (META_IS_SELECTION_SOURCE_MEMORY_POOL (pool)); -+ g_return_if_fail (META_IS_SELECTION_SOURCE_MEMORY (source)); -+ g_return_if_fail (g_list_find (pool->sources, source) != NULL); -+ -+ pool->sources = g_list_remove (pool->sources, source); -+ g_object_unref (source); -+} -+ -+void -+meta_selection_source_memory_pool_clear (MetaSelectionSourceMemoryPool *pool) -+{ -+ g_return_if_fail (META_IS_SELECTION_SOURCE_MEMORY_POOL (pool)); -+ -+ g_list_free_full (pool->sources, g_object_unref); -+ pool->sources = NULL; -+} -+ -+gboolean -+meta_selection_source_memory_pool_has_sources (MetaSelectionSourceMemoryPool *pool) -+{ -+ g_return_val_if_fail (META_IS_SELECTION_SOURCE_MEMORY_POOL (pool), FALSE); -+ -+ return g_list_length(pool->sources) == 2; -+ // return pool->sources != NULL; -+} diff --git a/src/core/window.c b/src/core/window.c -index ea721f7..e34868d 100644 +index cc9fd2f..732470b 100644 --- a/src/core/window.c +++ b/src/core/window.c @@ -227,6 +227,7 @@ enum diff -Nru mutter-3.36.1/debian/patches/x11-fix-compilation-if-libwacom-false.patch mutter-3.36.9/debian/patches/x11-fix-compilation-if-libwacom-false.patch --- mutter-3.36.1/debian/patches/x11-fix-compilation-if-libwacom-false.patch 2020-04-16 20:04:59.000000000 +0000 +++ mutter-3.36.9/debian/patches/x11-fix-compilation-if-libwacom-false.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,28 +0,0 @@ -From: Christian Rauch -Date: Tue, 31 Mar 2020 20:28:44 +0000 -Subject: x11: fix compilation if 'libwacom=false' - -https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1168 - -(cherry picked from commit a8f6cada883eda2a34e6478a53e2fb7c392d98b7) - -Origin: upstream, 3.36.2, commit:7baabc7ed0105dbf457fffe48250919849623254 ---- - src/backends/x11/meta-input-device-x11.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/backends/x11/meta-input-device-x11.c b/src/backends/x11/meta-input-device-x11.c -index 480acd8..2406c34 100644 ---- a/src/backends/x11/meta-input-device-x11.c -+++ b/src/backends/x11/meta-input-device-x11.c -@@ -122,9 +122,9 @@ meta_input_device_x11_is_grouped (ClutterInputDevice *device, - static void - meta_input_device_x11_finalize (GObject *object) - { --#ifdef HAVE_LIBWACOM - MetaInputDeviceX11 *device_xi2 = META_INPUT_DEVICE_X11 (object); - -+#ifdef HAVE_LIBWACOM - if (device_xi2->group_modes) - g_array_unref (device_xi2->group_modes); - #endif diff -Nru mutter-3.36.1/debian/rules mutter-3.36.9/debian/rules --- mutter-3.36.1/debian/rules 2020-04-17 01:07:54.000000000 +0000 +++ mutter-3.36.9/debian/rules 2021-11-03 19:10:34.000000000 +0000 @@ -38,9 +38,7 @@ ifeq ($(shell dpkg-vendor --query vendor),Ubuntu) CONFFLAGS += -Dremote_desktop=false else - # this depends on Pipewire 0.3, which is not packaged yet - # and is quite complicated (e.g. it replaces Pulseaudio) - CONFFLAGS += -Dremote_desktop=false + CONFFLAGS += -Dremote_desktop=true endif endif @@ -106,6 +104,3 @@ override_dh_shlibdeps: dh_shlibdeps -Llibmutter-6-0 -l/usr/lib/$(DEB_HOST_MULTIARCH)/mutter-6 - -override_dh_strip: - dh_strip --dbgsym-migration='mutter-dbg (<< 3.18.3-2~)' diff -Nru mutter-3.36.1/debian/watch mutter-3.36.9/debian/watch --- mutter-3.36.1/debian/watch 2020-04-16 20:04:59.000000000 +0000 +++ mutter-3.36.9/debian/watch 2021-11-03 19:10:34.000000000 +0000 @@ -1,3 +1,3 @@ version=4 -https://download.gnome.org/sources/@PACKAGE@/([\d\.]+)/ \ - @PACKAGE@@ANY_VERSION@@ARCHIVE_EXT@ +https://download.gnome.org/sources/@PACKAGE@/([\d\.]+36)/ \ + @PACKAGE@@ANY_VERSION@\.tar\.xz diff -Nru mutter-3.36.1/meson.build mutter-3.36.9/meson.build --- mutter-3.36.1/meson.build 2020-03-30 19:29:39.159888300 +0000 +++ mutter-3.36.9/meson.build 2021-03-15 23:07:33.152504000 +0000 @@ -1,5 +1,5 @@ project('mutter', 'c', - version: '3.36.1', + version: '3.36.9', meson_version: '>= 0.50.0', license: 'GPLv2+' ) diff -Nru mutter-3.36.1/meson_options.txt mutter-3.36.9/meson_options.txt --- mutter-3.36.1/meson_options.txt 2020-03-30 19:29:39.159888300 +0000 +++ mutter-3.36.9/meson_options.txt 2021-03-15 23:07:33.152504000 +0000 @@ -12,7 +12,7 @@ option('gles2_libname', type: 'string', - value: 'libGLESv2.so', + value: 'libGLESv2.so.2', description: 'GLESv2 library file name' ) diff -Nru mutter-3.36.1/NEWS mutter-3.36.9/NEWS --- mutter-3.36.1/NEWS 2020-03-30 19:29:39.044891000 +0000 +++ mutter-3.36.9/NEWS 2021-03-15 23:07:33.032507400 +0000 @@ -1,3 +1,137 @@ +3.36.9 +====== +* Do not ping unmanaging windows [Florian; gnome-shell#2467] +* Improve freezes when switching workspace [Jonas Å.; !1616] +* Fix drag cancel animation when using geometry scaling [Robert; !1683] +* Fix stuck icon in DND operation between X11 and wayland [Carlos; !1720] +* Fix restoring focus to windows using globally active input [Olivier; !1716] +* Fix order in which subsurface placement operations are handled [Robert; !1768] + +Contributors: + Jonas Ådahl, Olivier Fourdan, Carlos Garnacho, Robert Mader, Florian Müllner + +3.36.8 +====== +* Fix _NET_WM_FRAME_DRAWN timestamps [Jonas; !1360] +* Fix unwanted position changes on window resize + [Jonas, Olivier, Robert; !1477, !1495] +* Fix device configuration not being picked up on X11 [Carlos; !1553] +* Fix size hints with CSD [Christian, Olivier; !1598] +* Disable CRTCs if there is no monitor [Kai-Heng; !1561] +* Fixed crashes [Olivier, Robert, Jonas; !1529, !1534, #1521, !1563, !1653] +* Plugged memory leaks [Ray; !1225] +* Misc. bug fixes and cleanups [Olivier, Robert, Daniel, Carlos; !1575, + !1565, !1572, !1655] + +Contributors: + Jonas Ådahl, Kai-Heng Feng, Olivier Fourdan, Carlos Garnacho, Robert Mader, + Christian Rauch, Ray Strode, Daniel van Vugt + + +3.36.7 +====== +* Fix Night Light updates after DPMS [Jonas, Benjamin; #1392] +* Fix IM handling on X11 [Carlos; #1413] +* Fix resizing of attached modal dialogs on wayland [Jonas; !1446] +* Fix jumps when resizing windows using discrete steps [Jonas; #1447] +* Fixed crashes [Marco; !1371, #1345] +* Plugged Memory leaks [Ray; !1449, !1451] +* Misc. bug fixes and cleanups [Jonas, Carlos, Robert; !1218, !1460, !1463] + +Contributors: + Marco Trevisan (Treviño), Benjamin Berg, Carlos Garnacho, Robert Mader, + Ray Strode, Jonas Ådahl + +Translators: + Juliano de Souza Camargo [pt] + +3.36.6 +====== +* Fix stale cursor positions in remote desktop sessions [Georges; !1417] +* Limit mipmap levels when rendering background [Daniel; !1003] +* Improve support for Hangul input method [Carlos; !1423] +* Fixed crashes [Robert, Benjamin; !1411, !1409, !1408, !1415, !1392] +* Plugged memory leaks [Robert; #1292] +* Misc. bug fixes and cleanups [Daniel; !1298, !983] + +Contributors: + Benjamin Berg, Carlos Garnacho, Robert Mader, Georges Basile Stavracas Neto, + Daniel van Vugt + +3.36.5 +====== +* Screencast fixes and improvements [Jonas; !1351, !1365] +* Fix glitches when subsurfaces extend outside the toplevel [Robert; #1316] +* Mipmap background texture rendering [Daniel; !1347] +* Fix wine copy & paste [Sebastian; !1369] +* Plugged memory leaks [Marco, Thomas; !1195] + +Contributors: + Jonas Ådahl, Thomas Hindoe Paaboel Andersen, Sebastian Keller, Robert Mader, + Marco Trevisan (Treviño), Daniel van Vugt + +Translators: + Rafael Fontenelle [pt_BR] + +3.36.4 +====== +* Fix crash on area screenshots with fractional scaling [Sebastian; !1320] +* Do not paint textures of fully obscured windows [Robert; !1326] +* Turn off CRTCs as well when enabling DPMS [Michel; !1240] +* Improve selection support + [Robert, Carlos, Sebastian; !1330, !1193, !1253, !1255, !1293, !1350] +* Use a more appropriate combine function on opaque areas [Daniel; !1331] +* Fix remote desktop being broken without screencast session [Olivier; #1307] +* Fix popovers disappearing on wayland and HiDPI [Robert; #1312] +* Fixed crashes [Jonas Å.; !1317] +* Plugged memory leaks [Jonas Å.; !1283] +* Misc. bug fixes and cleanups + [Corentin, Sebastian, Jonas Å., Jonas D.; !1314, !1321, !1295, !1333] + +Contributors: + Jonas Dreßler, Michel Dänzer, Olivier Fourdan, Carlos Garnacho, + Sebastian Keller, Robert Mader, Corentin Noël, Daniel van Vugt, Jonas Ådahl + + +3.36.3 +====== +* Broadcast clipboard/primary offers [Carlos; !1262] +* Fix monitor screen cast on X11 [Jonas Å.; !1251] +* Implement touch-mode detecation for the X11 backend [Carlos; !1278] +* Drop external keyboard detection from touch-mode heuristics [Carlos; !1277] +* Fix leaked DMA buffers in screencasts [Jonas; !1283] +* Fixed crashes [Daniel, Carlos, Jonas D.; !1256, !1258, !1280] + +Contributors: + Carlos Garnacho, Daniel van Vugt, Jonas Ådahl + +3.36.2 +====== +* Sync timelines to hardware vsync [Daniel; !724] +* Fix screencasting non-maximized windows [Jonas; !1174] +* Make window-aliveness checks less aggressive [Jonas; !1182] +* Fix stylus coordinates when using screen rotation [Jonas T.; #1118] +* Preserve keyboard state on VT switch [Olivier; !1185] +* Fix trackball button scrolling [Phillip; #1120] +* Fix tiled monitor support [Jonas Å.; !1199] +* Fix various clipboard issues [Carlos; !1198, !1203, !1204, !1186, !1206] +* Synchronize shadows to server-side decorations [Olivier; !1214] +* Fix overview key on X11 when using multiple keyboard layouts [Olivier; !1219] +* Fix capturing with multiple stage views [Jonas Å.; !1222] +* Fixed crashes [Jonas D., Carlos; !1173, !1183] +* Misc. bug fixes and cleanups [Andre, Georges, Simon, Christian, Carlos, Marco, + Pekka, Laurent, Jonas D.; !1169, !1170, !1172, !1168, !1184, !1200, !1209, + #1074, !1208] + +Contributors: + Marco Trevisan (Treviño), Laurent Bigonville, Jonas Dreßler, Olivier Fourdan, + Carlos Garnacho, Andre Moreira Magalhaes, Simon McVittie, + Georges Basile Stavracas Neto, Pekka Paalanen, Christian Rauch, Jonas Troeger, + Daniel van Vugt, Phillip Wood, Jonas Ådahl + +Translators: + Dušan Kazik [sk], Christian Kirbach [de] + 3.36.1 ====== * Fix hardware cursor on GPU hotplpug [Pekka; !1097] diff -Nru mutter-3.36.1/po/de.po mutter-3.36.9/po/de.po --- mutter-3.36.1/po/de.po 2020-03-30 19:29:39.186887700 +0000 +++ mutter-3.36.9/po/de.po 2021-03-15 23:07:33.176503400 +0000 @@ -13,8 +13,8 @@ msgstr "" "Project-Id-Version: mutter master\n" "Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/mutter/issues\n" -"POT-Creation-Date: 2019-08-06 00:49+0000\n" -"PO-Revision-Date: 2019-09-05 23:42+0200\n" +"POT-Creation-Date: 2020-03-30 20:11+0000\n" +"PO-Revision-Date: 2020-04-06 23:13+0200\n" "Last-Translator: Christian Kirbach \n" "Language-Team: Deutsch \n" "Language: de\n" @@ -22,7 +22,7 @@ "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -"X-Generator: Poedit 2.2.1\n" +"X-Generator: Poedit 2.3\n" #: data/50-mutter-navigation.xml:6 msgid "Navigation" @@ -435,20 +435,33 @@ msgid "This key will initiate the “locate pointer” action." msgstr "Diese Taste wird die Aktion »Zeiger finden« auslösen." -#: data/org.gnome.mutter.gschema.xml.in:155 +#: data/org.gnome.mutter.gschema.xml.in:142 +msgid "Timeout for check-alive ping" +msgstr "Reaktionsschwellwert bei Kontaktkontrolle" + +#: data/org.gnome.mutter.gschema.xml.in:143 +msgid "" +"Number of milliseconds a client has to respond to a ping request in order to " +"not be detected as frozen. Using 0 will disable the alive check completely." +msgstr "" +"Zeit in Millisekunden, innerhalb welcher ein Client auf eine " +"Kontaktkontrolle antworten muss, um nicht als abgestürzt zu gelten. »0« " +"bedeutet, dass die Kontaktkontrolle ausgeschaltet wird." + +#: data/org.gnome.mutter.gschema.xml.in:165 msgid "Select window from tab popup" msgstr "Fenster aus Tab-Anzeige auswählen" -#: data/org.gnome.mutter.gschema.xml.in:160 +#: data/org.gnome.mutter.gschema.xml.in:170 msgid "Cancel tab popup" msgstr "Tab-Anzeige abbrechen" -#: data/org.gnome.mutter.gschema.xml.in:165 +#: data/org.gnome.mutter.gschema.xml.in:175 msgid "Switch monitor configurations" msgstr "Bildschirmkonfigurationen wechseln" # Ich denke nicht, dass »rotate« hier die Bildschirmdrehung meint, sondern eher eine Liste aus Konfigurationen rotiert (d.h. umgewälzt) wird. -#: data/org.gnome.mutter.gschema.xml.in:170 +#: data/org.gnome.mutter.gschema.xml.in:180 msgid "Rotates the built-in monitor configuration" msgstr "Wechselt die Konfiguration des eingebauten Bildschirms" @@ -569,7 +582,7 @@ #. TRANSLATORS: This string refers to a button that switches between #. * different modes. #. -#: src/backends/meta-input-settings.c:2531 +#: src/backends/meta-input-settings.c:2631 #, c-format msgid "Mode Switch (Group %d)" msgstr "Moduswechsel (Gruppe %d)" @@ -577,34 +590,34 @@ #. TRANSLATORS: This string refers to an action, cycles drawing tablets' #. * mapping through the available outputs. #. -#: src/backends/meta-input-settings.c:2554 +#: src/backends/meta-input-settings.c:2654 msgid "Switch monitor" msgstr "Bildschirm wechseln" -#: src/backends/meta-input-settings.c:2556 +#: src/backends/meta-input-settings.c:2656 msgid "Show on-screen help" msgstr "Bildschirmhilfe anzeigen" -#: src/backends/meta-monitor.c:223 +#: src/backends/meta-monitor.c:226 msgid "Built-in display" msgstr "Eingebaute Anzeige" -#: src/backends/meta-monitor.c:252 +#: src/backends/meta-monitor.c:255 msgid "Unknown" msgstr "Unbekannt" -#: src/backends/meta-monitor.c:254 +#: src/backends/meta-monitor.c:257 msgid "Unknown Display" msgstr "Unbekannte Anzeige" -#: src/backends/meta-monitor.c:262 +#: src/backends/meta-monitor.c:265 #, c-format msgctxt "" "This is a monitor vendor name, followed by a size in inches, like 'Dell 15\"'" msgid "%s %s" msgstr "%s %s" -#: src/backends/meta-monitor.c:270 +#: src/backends/meta-monitor.c:273 #, c-format msgctxt "" "This is a monitor vendor name followed by product/model name where size in " @@ -614,13 +627,13 @@ # https://de.wikipedia.org/wiki/Composition-Manager #. Translators: this string will appear in Sysprof -#: src/backends/meta-profiler.c:82 +#: src/backends/meta-profiler.c:79 msgid "Compositor" msgstr "Compositor" #. This probably means that a non-WM compositor like xcompmgr is running; #. * we have no way to get it to exit -#: src/compositor/compositor.c:510 +#: src/compositor/compositor.c:533 #, c-format msgid "" "Another compositing manager is already running on screen %i on display “%s”." @@ -632,47 +645,47 @@ msgid "Bell event" msgstr "Klangereignis" -#: src/core/main.c:185 +#: src/core/main.c:190 msgid "Disable connection to session manager" msgstr "Verbindung zur Sitzungsverwaltung deaktivieren" -#: src/core/main.c:191 +#: src/core/main.c:196 msgid "Replace the running window manager" msgstr "Den aktuellen Fensterverwalter ersetzen" -#: src/core/main.c:197 +#: src/core/main.c:202 msgid "Specify session management ID" msgstr "Kennung der Sitzungsverwaltung angeben" -#: src/core/main.c:202 +#: src/core/main.c:207 msgid "X Display to use" msgstr "Zu verwendende X-Anzeige" -#: src/core/main.c:208 +#: src/core/main.c:213 msgid "Initialize session from savefile" msgstr "Sitzung anhand gespeicherter Datei starten" -#: src/core/main.c:214 +#: src/core/main.c:219 msgid "Make X calls synchronous" msgstr "X-Aufrufe abgleichen" -#: src/core/main.c:221 +#: src/core/main.c:226 msgid "Run as a wayland compositor" msgstr "Als Wayland-Compositor ausführen" -#: src/core/main.c:227 +#: src/core/main.c:232 msgid "Run as a nested compositor" msgstr "Als eingebetteten Compositor ausführen" -#: src/core/main.c:233 +#: src/core/main.c:238 msgid "Run wayland compositor without starting Xwayland" msgstr "Wayland-Compositor ausführen, ohne Xwayland zu starten" -#: src/core/main.c:241 +#: src/core/main.c:246 msgid "Run as a full display server, rather than nested" msgstr "Als vollwertigen Display-Server verwenden (nicht eingebettet)" -#: src/core/main.c:247 +#: src/core/main.c:252 msgid "Run with X11 backend" msgstr "Mit X11-Backend ausführen" @@ -728,21 +741,21 @@ msgid "Mutter plugin to use" msgstr "Zu benutzendes Mutter-Plugin" -#: src/core/prefs.c:1849 +#: src/core/prefs.c:1911 #, c-format msgid "Workspace %d" msgstr "Arbeitsfläche %d" -#: src/core/util.c:121 +#: src/core/util.c:122 msgid "Mutter was compiled without support for verbose mode\n" msgstr "Mutter wurde ohne Unterstützung für den redseligen Modus kompiliert\n" -#: src/wayland/meta-wayland-tablet-pad.c:567 +#: src/wayland/meta-wayland-tablet-pad.c:568 #, c-format msgid "Mode Switch: Mode %d" msgstr "Moduswechsel: Modus %d" -#: src/x11/meta-x11-display.c:671 +#: src/x11/meta-x11-display.c:676 #, c-format msgid "" "Display “%s” already has a window manager; try using the --replace option to " @@ -751,21 +764,21 @@ "Bildschirm »%s« hat bereits einen Fensterverwalter. Versuchen Sie die Option " "»--replace«, um den aktuellen Fensterverwalter zu ersetzen." -#: src/x11/meta-x11-display.c:1032 +#: src/x11/meta-x11-display.c:1089 msgid "Failed to initialize GDK\n" msgstr "GDK konnte nicht initialisiert werden\n" -#: src/x11/meta-x11-display.c:1056 +#: src/x11/meta-x11-display.c:1113 #, c-format msgid "Failed to open X Window System display “%s”\n" msgstr "X-Window-Systemanzeige »%s« konnte nicht geöffnet werden\n" -#: src/x11/meta-x11-display.c:1140 +#: src/x11/meta-x11-display.c:1196 #, c-format msgid "Screen %d on display “%s” is invalid\n" msgstr "Bildschirm %d auf Anzeige »%s« ist ungültig\n" -#: src/x11/meta-x11-selection-input-stream.c:445 +#: src/x11/meta-x11-selection-input-stream.c:460 #, c-format msgid "Format %s not supported" msgstr "Format %s wird nicht unterstützt" diff -Nru mutter-3.36.1/po/pt_BR.po mutter-3.36.9/po/pt_BR.po --- mutter-3.36.1/po/pt_BR.po 2020-03-30 19:29:39.244886400 +0000 +++ mutter-3.36.9/po/pt_BR.po 2021-03-15 23:07:33.228502000 +0000 @@ -21,8 +21,8 @@ msgstr "" "Project-Id-Version: mutter\n" "Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/mutter/issues\n" -"POT-Creation-Date: 2020-02-23 17:41+0000\n" -"PO-Revision-Date: 2020-02-24 06:39-0300\n" +"POT-Creation-Date: 2020-04-27 14:06+0000\n" +"PO-Revision-Date: 2020-07-17 17:56-0300\n" "Last-Translator: Rafael Fontenelle \n" "Language-Team: Brazilian Portuguese \n" "Language: pt_BR\n" @@ -30,7 +30,7 @@ "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n > 1)\n" -"X-Generator: Gtranslator 3.32.0\n" +"X-Generator: Gtranslator 3.36.0\n" "X-Project-Style: gnome\n" #: data/50-mutter-navigation.xml:6 @@ -59,35 +59,35 @@ #: data/50-mutter-navigation.xml:24 msgid "Move window one workspace up" -msgstr "Mover a janela um espaço de trabalho acima" +msgstr "Mover a janela para um espaço de trabalho acima" #: data/50-mutter-navigation.xml:27 msgid "Move window one workspace down" -msgstr "Mover a janela um espaço de trabalho abaixo" +msgstr "Mover a janela para um espaço de trabalho abaixo" # Em conformidade com a tradução do gsettings-desktop-schemas --Enrico #: data/50-mutter-navigation.xml:30 msgid "Move window one monitor to the left" -msgstr "Mover janela para o monitor da esquerda" +msgstr "Mover a janela para o monitor da esquerda" # Em conformidade com a tradução do gsettings-desktop-schemas --Enrico #: data/50-mutter-navigation.xml:33 msgid "Move window one monitor to the right" -msgstr "Mover janela para o monitor da direita" +msgstr "Mover a janela para o monitor da direita" # Em conformidade com a tradução do gsettings-desktop-schemas --Enrico #: data/50-mutter-navigation.xml:36 msgid "Move window one monitor up" -msgstr "Mover janela para o monitor acima" +msgstr "Mover a janela para o monitor acima" # Em conformidade com a tradução do gsettings-desktop-schemas --Enrico #: data/50-mutter-navigation.xml:39 msgid "Move window one monitor down" -msgstr "Mover janela para o monitor abaixo" +msgstr "Mover a janela para o monitor abaixo" #: data/50-mutter-navigation.xml:43 msgid "Switch applications" -msgstr "Alternar aplicativos" +msgstr "Alternar entre aplicativos" #: data/50-mutter-navigation.xml:48 msgid "Switch to previous application" @@ -95,7 +95,7 @@ #: data/50-mutter-navigation.xml:52 msgid "Switch windows" -msgstr "Alternar janelas" +msgstr "Alternar entre janelas" #: data/50-mutter-navigation.xml:57 msgid "Switch to previous window" @@ -111,7 +111,7 @@ #: data/50-mutter-navigation.xml:70 msgid "Switch system controls" -msgstr "Alternar controles do sistema" +msgstr "Alternar os controles do sistema" #: data/50-mutter-navigation.xml:75 msgid "Switch to previous system control" @@ -167,11 +167,11 @@ #: data/50-mutter-navigation.xml:123 msgid "Move to workspace above" -msgstr "Mover para o espaço de trabalho acima" +msgstr "Mover a visualização para o espaço de trabalho acima" #: data/50-mutter-navigation.xml:126 msgid "Move to workspace below" -msgstr "Mover para o espaço de trabalho abaixo" +msgstr "Mover a visualização para o espaço de trabalho abaixo" #: data/50-mutter-system.xml:6 data/50-mutter-wayland.xml:6 msgid "System" @@ -199,11 +199,11 @@ #: data/50-mutter-windows.xml:10 msgid "Toggle fullscreen mode" -msgstr "Alternar modo de tela inteira" +msgstr "Alternar o modo de tela inteira" #: data/50-mutter-windows.xml:12 msgid "Toggle maximization state" -msgstr "Alternar estado de maximização" +msgstr "Alternar o estado de maximização" #: data/50-mutter-windows.xml:14 msgid "Maximize window" @@ -211,35 +211,35 @@ #: data/50-mutter-windows.xml:16 msgid "Restore window" -msgstr "Restaurar janela" +msgstr "Restaurar a anela" #: data/50-mutter-windows.xml:18 msgid "Close window" -msgstr "Fechar janela" +msgstr "Fechar a janela" #: data/50-mutter-windows.xml:20 msgid "Hide window" -msgstr "Ocultar janela" +msgstr "Ocultar a janela" #: data/50-mutter-windows.xml:22 msgid "Move window" -msgstr "Mover janela" +msgstr "Mover a janela" #: data/50-mutter-windows.xml:24 msgid "Resize window" -msgstr "Redimensionar janela" +msgstr "Redimensionar a janela" #: data/50-mutter-windows.xml:27 msgid "Toggle window on all workspaces or one" -msgstr "Alternar a janela em todos os espaços de trabalho ou em apenas um" +msgstr "Alternar a janela em todos os espaços de trabalho ou apenas em um" #: data/50-mutter-windows.xml:29 msgid "Raise window if covered, otherwise lower it" -msgstr "Elevar a janela se estiver coberta; caso contrário, a abaixa" +msgstr "Trazer a janela se estiver coberta; caso contrário, coloca atrás" #: data/50-mutter-windows.xml:31 msgid "Raise window above other windows" -msgstr "Elevar a janela para frente das outras" +msgstr "Trazer a janela para frente das outras" #: data/50-mutter-windows.xml:33 msgid "Lower window below other windows" @@ -255,11 +255,11 @@ #: data/50-mutter-windows.xml:41 msgid "View split on left" -msgstr "Visualizar divisão à esquerda" +msgstr "Visualizar a divisão à esquerda" #: data/50-mutter-windows.xml:45 msgid "View split on right" -msgstr "Visualizar divisão à direita" +msgstr "Visualizar a divisão à direita" #: data/mutter.desktop.in:4 msgid "Mutter" @@ -580,7 +580,7 @@ #. TRANSLATORS: This string refers to a button that switches between #. * different modes. #. -#: src/backends/meta-input-settings.c:2567 +#: src/backends/meta-input-settings.c:2631 #, c-format msgid "Mode Switch (Group %d)" msgstr "Alternador de modo (Grupo %d)" @@ -588,34 +588,34 @@ #. TRANSLATORS: This string refers to an action, cycles drawing tablets' #. * mapping through the available outputs. #. -#: src/backends/meta-input-settings.c:2590 +#: src/backends/meta-input-settings.c:2654 msgid "Switch monitor" msgstr "Trocar monitor" -#: src/backends/meta-input-settings.c:2592 +#: src/backends/meta-input-settings.c:2656 msgid "Show on-screen help" msgstr "Mostrar ajuda na tela" -#: src/backends/meta-monitor.c:223 +#: src/backends/meta-monitor.c:226 msgid "Built-in display" msgstr "Tela embutida" -#: src/backends/meta-monitor.c:252 +#: src/backends/meta-monitor.c:255 msgid "Unknown" msgstr "Desconhecido" -#: src/backends/meta-monitor.c:254 +#: src/backends/meta-monitor.c:257 msgid "Unknown Display" msgstr "Monitor desconhecido" -#: src/backends/meta-monitor.c:262 +#: src/backends/meta-monitor.c:265 #, c-format msgctxt "" "This is a monitor vendor name, followed by a size in inches, like 'Dell 15\"'" msgid "%s %s" msgstr "%s %s" -#: src/backends/meta-monitor.c:270 +#: src/backends/meta-monitor.c:273 #, c-format msgctxt "" "This is a monitor vendor name followed by product/model name where size in " diff -Nru mutter-3.36.1/po/pt.po mutter-3.36.9/po/pt.po --- mutter-3.36.1/po/pt.po 2020-03-30 19:29:39.243886500 +0000 +++ mutter-3.36.9/po/pt.po 2021-03-15 23:07:33.228502000 +0000 @@ -4,22 +4,22 @@ # Duarte Loreto , 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014. # Pedro Albuquerque , 2015. # Tiago Santos , 2016. +# Juliano de Souza Camargo , 2020. # msgid "" msgstr "" "Project-Id-Version: 3.10\n" -"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" -"product=mutter&keywords=I18N+L10N&component=general\n" -"POT-Creation-Date: 2016-09-07 09:27+0000\n" -"PO-Revision-Date: 2016-09-09 17:59+0100\n" -"Last-Translator: Tiago Santos \n" -"Language-Team: Português\n" +"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/mutter/issues\n" +"POT-Creation-Date: 2020-05-29 14:52+0000\n" +"PO-Revision-Date: 2020-09-14 21:15-0300\n" +"Last-Translator: Juliano de Souza Camargo \n" +"Language-Team: Portuguese <>\n" "Language: pt\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Generator: Poedit 1.8.7.1\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: Gtranslator 3.36.0\n" +"Plural-Forms: nplurals=2; plural=(n != 1)\n" #: data/50-mutter-navigation.xml:6 msgid "Navigation" @@ -46,134 +46,118 @@ msgstr "Mover janela para a última área de trabalho" #: data/50-mutter-navigation.xml:24 -msgid "Move window one workspace to the left" -msgstr "Mover a janela uma área de trabalho para a esquerda" - -#: data/50-mutter-navigation.xml:27 -msgid "Move window one workspace to the right" -msgstr "Mover a janela uma área de trabalho para a direita" - -#: data/50-mutter-navigation.xml:30 msgid "Move window one workspace up" msgstr "Mover a janela uma área de trabalho acima" -#: data/50-mutter-navigation.xml:33 +#: data/50-mutter-navigation.xml:27 msgid "Move window one workspace down" msgstr "Mover a janela uma área de trabalho abaixo" -#: data/50-mutter-navigation.xml:36 +#: data/50-mutter-navigation.xml:30 msgid "Move window one monitor to the left" msgstr "Mover a janela um monitor para a esquerda" -#: data/50-mutter-navigation.xml:39 +#: data/50-mutter-navigation.xml:33 msgid "Move window one monitor to the right" msgstr "Mover a janela um monitor para a direita" -#: data/50-mutter-navigation.xml:42 +#: data/50-mutter-navigation.xml:36 msgid "Move window one monitor up" msgstr "Mover a janela um monitor acima" -#: data/50-mutter-navigation.xml:45 +#: data/50-mutter-navigation.xml:39 msgid "Move window one monitor down" msgstr "Mover a janela um monitor abaixo" -#: data/50-mutter-navigation.xml:49 +#: data/50-mutter-navigation.xml:43 msgid "Switch applications" msgstr "Mudar de aplicações" -#: data/50-mutter-navigation.xml:54 +#: data/50-mutter-navigation.xml:48 msgid "Switch to previous application" msgstr "Mudar para a aplicação anterior" -#: data/50-mutter-navigation.xml:58 +#: data/50-mutter-navigation.xml:52 msgid "Switch windows" msgstr "Mudar de janelas" -#: data/50-mutter-navigation.xml:63 +#: data/50-mutter-navigation.xml:57 msgid "Switch to previous window" msgstr "Mudar para a janela anterior" -#: data/50-mutter-navigation.xml:67 +#: data/50-mutter-navigation.xml:61 msgid "Switch windows of an application" msgstr "Alternar entre janelas de uma aplicação" -#: data/50-mutter-navigation.xml:72 +#: data/50-mutter-navigation.xml:66 msgid "Switch to previous window of an application" msgstr "Mudar para a janela anterior de uma aplicação" -#: data/50-mutter-navigation.xml:76 +#: data/50-mutter-navigation.xml:70 msgid "Switch system controls" msgstr "Alternar controlos de sistema" -#: data/50-mutter-navigation.xml:81 +#: data/50-mutter-navigation.xml:75 msgid "Switch to previous system control" msgstr "Mudar para o controlo de sistema anterior" -#: data/50-mutter-navigation.xml:85 +#: data/50-mutter-navigation.xml:79 msgid "Switch windows directly" msgstr "Alternar diretamente entre janelas" -#: data/50-mutter-navigation.xml:90 +#: data/50-mutter-navigation.xml:84 msgid "Switch directly to previous window" msgstr "Mudar diretamente para a janela anterior" -#: data/50-mutter-navigation.xml:94 +#: data/50-mutter-navigation.xml:88 msgid "Switch windows of an app directly" msgstr "Alternar diretamente entre janelas de uma aplicação" -#: data/50-mutter-navigation.xml:99 +#: data/50-mutter-navigation.xml:93 msgid "Switch directly to previous window of an app" msgstr "Mudar diretamente para a janela anterior de uma aplicação" -#: data/50-mutter-navigation.xml:103 +#: data/50-mutter-navigation.xml:97 msgid "Switch system controls directly" msgstr "Alternar diretamente entre controlos de sistema" -#: data/50-mutter-navigation.xml:108 +#: data/50-mutter-navigation.xml:102 msgid "Switch directly to previous system control" msgstr "Mudar diretamente para o controlo de sistema anterior" -#: data/50-mutter-navigation.xml:111 +#: data/50-mutter-navigation.xml:105 msgid "Hide all normal windows" msgstr "Ocultar todas as janelas normais" -#: data/50-mutter-navigation.xml:114 +#: data/50-mutter-navigation.xml:108 msgid "Switch to workspace 1" msgstr "Mudar para a área de trabalho 1" -#: data/50-mutter-navigation.xml:117 +#: data/50-mutter-navigation.xml:111 msgid "Switch to workspace 2" msgstr "Mudar para a área de trabalho 2" -#: data/50-mutter-navigation.xml:120 +#: data/50-mutter-navigation.xml:114 msgid "Switch to workspace 3" msgstr "Mudar para a área de trabalho 3" -#: data/50-mutter-navigation.xml:123 +#: data/50-mutter-navigation.xml:117 msgid "Switch to workspace 4" msgstr "Mudar para a área de trabalho 4" -#: data/50-mutter-navigation.xml:126 +#: data/50-mutter-navigation.xml:120 msgid "Switch to last workspace" msgstr "Mudar para a última área de trabalho 1" -#: data/50-mutter-navigation.xml:129 -msgid "Move to workspace left" -msgstr "Mover para a área de trabalho à esquerda" - -#: data/50-mutter-navigation.xml:132 -msgid "Move to workspace right" -msgstr "Mover para a área de trabalho à direita" - -#: data/50-mutter-navigation.xml:135 +#: data/50-mutter-navigation.xml:123 msgid "Move to workspace above" msgstr "Mover para a área de trabalho acima" -#: data/50-mutter-navigation.xml:138 +#: data/50-mutter-navigation.xml:126 msgid "Move to workspace below" msgstr "Mover para a área de trabalho abaixo" -#: data/50-mutter-system.xml:6 +#: data/50-mutter-system.xml:6 data/50-mutter-wayland.xml:6 msgid "System" msgstr "Sistema" @@ -185,6 +169,10 @@ msgid "Show the activities overview" msgstr "Mostrar o resumo de atividades" +#: data/50-mutter-wayland.xml:8 +msgid "Restore the keyboard shortcuts" +msgstr "Redefinir os atalhos de teclado" + #: data/50-mutter-windows.xml:6 msgid "Windows" msgstr "Janelas" @@ -210,54 +198,50 @@ msgstr "Restaurar a janela" #: data/50-mutter-windows.xml:18 -msgid "Toggle shaded state" -msgstr "Alternar estado sombreado" - -#: data/50-mutter-windows.xml:20 msgid "Close window" msgstr "Fechar a janela" -#: data/50-mutter-windows.xml:22 +#: data/50-mutter-windows.xml:20 msgid "Hide window" msgstr "Esconder a janela" -#: data/50-mutter-windows.xml:24 +#: data/50-mutter-windows.xml:22 msgid "Move window" msgstr "Mover a janela" -#: data/50-mutter-windows.xml:26 +#: data/50-mutter-windows.xml:24 msgid "Resize window" msgstr "Redimensionar a janela" -#: data/50-mutter-windows.xml:29 +#: data/50-mutter-windows.xml:27 msgid "Toggle window on all workspaces or one" msgstr "Alternar janela em todas as áreas de trabalho ou só numa" -#: data/50-mutter-windows.xml:31 +#: data/50-mutter-windows.xml:29 msgid "Raise window if covered, otherwise lower it" msgstr "Elevar a janela se estiver tapada, caso contrário baixá-la" -#: data/50-mutter-windows.xml:33 +#: data/50-mutter-windows.xml:31 msgid "Raise window above other windows" msgstr "Elevar janela acima de outras janelas" -#: data/50-mutter-windows.xml:35 +#: data/50-mutter-windows.xml:33 msgid "Lower window below other windows" msgstr "Baixar janela abaixo de outras janelas" -#: data/50-mutter-windows.xml:37 +#: data/50-mutter-windows.xml:35 msgid "Maximize window vertically" msgstr "Maximizar janela verticalmente" -#: data/50-mutter-windows.xml:39 +#: data/50-mutter-windows.xml:37 msgid "Maximize window horizontally" msgstr "Maximizar janela horizontalmente" -#: data/50-mutter-windows.xml:43 +#: data/50-mutter-windows.xml:41 msgid "View split on left" msgstr "Ver a divisão à esquerda" -#: data/50-mutter-windows.xml:47 +#: data/50-mutter-windows.xml:45 msgid "View split on right" msgstr "Ver a divisão à direita" @@ -270,11 +254,16 @@ msgstr "Modificador a utilizar para operações estendidas de gestão de janelas" #: data/org.gnome.mutter.gschema.xml.in:8 +#| msgid "" +#| "This key will initiate the \"overlay\", which is a combination window " +#| "overview and application launching system. The default is intended to be " +#| "the \"Windows key\" on PC hardware. It's expected that this binding " +#| "either the default or set to the empty string." msgid "" -"This key will initiate the \"overlay\", which is a combination window " -"overview and application launching system. The default is intended to be the " -"\"Windows key\" on PC hardware. It's expected that this binding either the " -"default or set to the empty string." +"This key will initiate the “overlay”, which is a combination window overview " +"and application launching system. The default is intended to be the “Windows " +"key” on PC hardware. It’s expected that this binding either the default or " +"set to the empty string." msgstr "" "Esta chave irá iniciar a \"sobreposição\", que é um sistema de visão " "combinada de janelas e arranque de aplicações. A predefinição é a \"tecla " @@ -315,8 +304,12 @@ msgstr "Áreas de trabalho geridas dinamicamente" #: data/org.gnome.mutter.gschema.xml.in:41 +#| msgid "" +#| "Determines whether workspaces are managed dynamically or whether there's " +#| "a static number of workspaces (determined by the num-workspaces key in " +#| "org.gnome.desktop.wm.preferences)." msgid "" -"Determines whether workspaces are managed dynamically or whether there's a " +"Determines whether workspaces are managed dynamically or whether there’s a " "static number of workspaces (determined by the num-workspaces key in org." "gnome.desktop.wm.preferences)." msgstr "" @@ -353,10 +346,14 @@ msgstr "Adiar as alterações de foco até que o ponteiro pare de se mover" #: data/org.gnome.mutter.gschema.xml.in:69 +#| msgid "" +#| "If set to true, and the focus mode is either \"sloppy\" or \"mouse\" then " +#| "the focus will not be changed immediately when entering a window, but " +#| "only after the pointer stops moving." msgid "" -"If set to true, and the focus mode is either \"sloppy\" or \"mouse\" then " -"the focus will not be changed immediately when entering a window, but only " -"after the pointer stops moving." +"If set to true, and the focus mode is either “sloppy” or “mouse” then the " +"focus will not be changed immediately when entering a window, but only after " +"the pointer stops moving." msgstr "" "Se verdadeiro, e o modo de foco for \"sloppy\" ou \"mouse\" então o foco não " "será alterado imediatamente ao entrar numa janela mas apenas quando o " @@ -367,8 +364,11 @@ msgstr "Largura da margem de arrasto" #: data/org.gnome.mutter.gschema.xml.in:80 +#| msgid "" +#| "The amount of total draggable borders. If the theme's visible borders are " +#| "not enough, invisible borders will be added to meet this value." msgid "" -"The amount of total draggable borders. If the theme's visible borders are " +"The amount of total draggable borders. If the theme’s visible borders are " "not enough, invisible borders will be added to meet this value." msgstr "" "A quantidade de margem total arrastável. Se as margens visíveis do tema não " @@ -399,14 +399,76 @@ "Se ativo, as novas janelas são sempre posicionadas no centro do ecrã do " "monitor ativo." -#: data/org.gnome.mutter.gschema.xml.in:120 +#: data/org.gnome.mutter.gschema.xml.in:107 +msgid "Enable experimental features" +msgstr "Ativar as funcionalidades experimentais" + +#: data/org.gnome.mutter.gschema.xml.in:108 +#, fuzzy +msgid "" +"To enable experimental features, add the feature keyword to the list. " +"Whether the feature requires restarting the compositor depends on the given " +"feature. Any experimental feature is not required to still be available, or " +"configurable. Don’t expect adding anything in this setting to be future " +"proof. Currently possible keywords: • “scale-monitor-framebuffer” — makes " +"mutter default to layout logical monitors in a logical pixel coordinate " +"space, while scaling monitor framebuffers instead of window content, to " +"manage HiDPI monitors. Does not require a restart. • “rt-scheduler” — makes " +"mutter request a low priority real-time scheduling. The executable or user " +"must have CAP_SYS_NICE. Requires a restart. • “autostart-xwayland” — " +"initializes Xwayland lazily if there are X11 clients. Requires restart." +msgstr "" +"Para ativar as funcionalidades experimentais, adicione a palavra-chave da " +"funcionalidade na lista. Se deve reiniciar o compositor após ativá-la, " +"depende de cada funcionalidade. Qualquer funcionalidade experimental não " +"necessita de estar disponível ou configurável. Não espere que adicionar algo " +"nas definições seja mantido pode tempo indeterminado. Atualmente as palavras-" +"chave são: • “scale-monitor-framebuffer” — makes mutter default to layout " +"logical monitors in a logical pixel coordinate space, while scaling monitor " +"framebuffers instead of window content, to manage HiDPI monitors. Does not " +"require a restart. • “rt-scheduler” — makes mutter request a low priority " +"real-time scheduling. The executable or user must have CAP_SYS_NICE. " +"Requires a restart. • “autostart-xwayland” — initializes Xwayland lazily if " +"there are X11 clients. Requires restart." + +#: data/org.gnome.mutter.gschema.xml.in:134 +msgid "Modifier to use to locate the pointer" +msgstr "Modificador para localizar o ponteiro" + +#: data/org.gnome.mutter.gschema.xml.in:135 +msgid "This key will initiate the “locate pointer” action." +msgstr "Esta chave inicializa a ação “localizar ponteiro”" + +#: data/org.gnome.mutter.gschema.xml.in:142 +msgid "Timeout for check-alive ping" +msgstr "Expirou o teste de atividade " + +#: data/org.gnome.mutter.gschema.xml.in:143 +msgid "" +"Number of milliseconds a client has to respond to a ping request in order to " +"not be detected as frozen. Using 0 will disable the alive check completely." +msgstr "" +"Número em milissegundos que um cliente precisa responder a um teste de " +"atividade de maneira que não seja detetado como inativo. Usar 0 desativará o " +"teste de atividade completamente." + +#: data/org.gnome.mutter.gschema.xml.in:165 msgid "Select window from tab popup" msgstr "Selecionar a janela no popup de tabulador" -#: data/org.gnome.mutter.gschema.xml.in:125 +#: data/org.gnome.mutter.gschema.xml.in:170 msgid "Cancel tab popup" msgstr "Cancelar o popup de tabulador" +#: data/org.gnome.mutter.gschema.xml.in:175 +#| msgid "Switch monitor" +msgid "Switch monitor configurations" +msgstr "Alternar configurações de ecrã" + +#: data/org.gnome.mutter.gschema.xml.in:180 +msgid "Rotates the built-in monitor configuration" +msgstr "Alternar as configurações nativas do ecrã" + #: data/org.gnome.mutter.wayland.gschema.xml.in:6 msgid "Switch to VT 1" msgstr "Alternar para a área de trabalho 1" @@ -455,120 +517,197 @@ msgid "Switch to VT 12" msgstr "Mover para a área de trabalho 12" -#: src/backends/meta-input-settings.c:1707 +#: data/org.gnome.mutter.wayland.gschema.xml.in:54 +msgid "Re-enable shortcuts" +msgstr "Reativar os atalhos" + +#: data/org.gnome.mutter.wayland.gschema.xml.in:64 +msgid "Allow X11 grabs to lock keyboard focus with Xwayland" +msgstr "" + +#: data/org.gnome.mutter.wayland.gschema.xml.in:65 +msgid "" +"Allow all keyboard events to be routed to X11 “override redirect” windows " +"with a grab when running in Xwayland. This option is to support X11 clients " +"which map an “override redirect” window (which do not receive keyboard " +"focus) and issue a keyboard grab to force all keyboard events to that " +"window. This option is seldom used and has no effect on regular X11 windows " +"which can receive keyboard focus under normal circumstances. For a X11 grab " +"to be taken into account under Wayland, the client must also either send a " +"specific X11 ClientMessage to the root window or be among the applications " +"white-listed in key “xwayland-grab-access-rules”." +msgstr "" + +#: data/org.gnome.mutter.wayland.gschema.xml.in:84 +msgid "Xwayland applications allowed to issue keyboard grabs" +msgstr "" + +#: data/org.gnome.mutter.wayland.gschema.xml.in:85 +msgid "" +"List the resource names or resource class of X11 windows either allowed or " +"not allowed to issue X11 keyboard grabs under Xwayland. The resource name or " +"resource class of a given X11 window can be obtained using the command " +"“xprop WM_CLASS”. Wildcards “*” and jokers “?” in the values are supported. " +"Values starting with “!” are blacklisted, which has precedence over the " +"whitelist, to revoke applications from the default system list. The default " +"system list includes the following applications: " +"“@XWAYLAND_GRAB_DEFAULT_ACCESS_RULES@” Users can break an existing grab by " +"using the specific keyboard shortcut defined by the keybinding key “restore-" +"shortcuts”." +msgstr "" + +#. TRANSLATORS: This string refers to a button that switches between +#. * different modes. +#. +#: src/backends/meta-input-settings.c:2631 +#, c-format +#| msgid "Mode Switch: Mode %d" +msgid "Mode Switch (Group %d)" +msgstr "Alteração de modo (Grupo %d)" + +#. TRANSLATORS: This string refers to an action, cycles drawing tablets' +#. * mapping through the available outputs. +#. +#: src/backends/meta-input-settings.c:2654 msgid "Switch monitor" msgstr "Alternar monitor" -#: src/backends/meta-input-settings.c:1709 +#: src/backends/meta-input-settings.c:2656 msgid "Show on-screen help" msgstr "Mostrar ajuda no ecrã" -#: src/backends/meta-monitor-manager.c:514 +#: src/backends/meta-monitor.c:226 msgid "Built-in display" msgstr "Ecrã embutido" -#: src/backends/meta-monitor-manager.c:537 +#: src/backends/meta-monitor.c:255 msgid "Unknown" msgstr "Desconhecido" -#: src/backends/meta-monitor-manager.c:539 +#: src/backends/meta-monitor.c:257 msgid "Unknown Display" msgstr "Ecrã desconhecido" -#. TRANSLATORS: this is a monitor vendor name, followed by a -#. * size in inches, like 'Dell 15"' -#. -#: src/backends/meta-monitor-manager.c:547 +#: src/backends/meta-monitor.c:265 #, c-format +#| msgid "%s %s" +msgctxt "" +"This is a monitor vendor name, followed by a size in inches, like 'Dell 15\"'" msgid "%s %s" msgstr "%s %s" +#: src/backends/meta-monitor.c:273 +#, c-format +#| msgid "%s %s" +msgctxt "" +"This is a monitor vendor name followed by product/model name where size in " +"inches could not be calculated, e.g. Dell U2414H" +msgid "%s %s" +msgstr "%s %s" + +#. Translators: this string will appear in Sysprof +#: src/backends/meta-profiler.c:79 +#| msgid "Compositing Manager" +msgid "Compositor" +msgstr "Compositor" + #. This probably means that a non-WM compositor like xcompmgr is running; #. * we have no way to get it to exit -#: src/compositor/compositor.c:463 +#: src/compositor/compositor.c:533 #, c-format +#| msgid "" +#| "Another compositing manager is already running on screen %i on display " +#| "\"%s\"." msgid "" -"Another compositing manager is already running on screen %i on display \"%s" -"\"." +"Another compositing manager is already running on screen %i on display “%s”." msgstr "" -"Já se encontra em execução outro gestor de janelas no ecrã %i do monitor \"%s" -"\"." +"Já se encontra em execução outro gestor de janelas no ecrã %i do ecrã “%s”." -#: src/core/bell.c:194 +#: src/core/bell.c:192 msgid "Bell event" msgstr "Evento de campainha" -#: src/core/delete.c:127 -#, c-format -msgid "“%s” is not responding." -msgstr "“%s” não está a responder." - -#: src/core/delete.c:129 -msgid "Application is not responding." -msgstr "A aplicação não está a responder." - -#: src/core/delete.c:134 -msgid "" -"You may choose to wait a short while for it to continue or force the " -"application to quit entirely." -msgstr "" -"Poderá aguardar uns instantes para que continue ou forçar a aplicação a " -"terminar definitivamente." - -#: src/core/delete.c:141 -msgid "_Wait" -msgstr "_Aguardar" - -#: src/core/delete.c:141 -msgid "_Force Quit" -msgstr "_Forçar terminar" - -#: src/core/display.c:590 -#, c-format -msgid "Failed to open X Window System display '%s'\n" -msgstr "Falha ao abrir ecrã \"%s\" do sistema Janelas X\n" - -#: src/core/main.c:182 +#: src/core/main.c:190 msgid "Disable connection to session manager" msgstr "Desativar a ligação ao gestor de sessão" -#: src/core/main.c:188 +#: src/core/main.c:196 msgid "Replace the running window manager" msgstr "Substituir o gestor de janelas em execução" -#: src/core/main.c:194 +#: src/core/main.c:202 msgid "Specify session management ID" msgstr "Especificar a ID de gestão de sessão" -#: src/core/main.c:199 +#: src/core/main.c:207 msgid "X Display to use" msgstr "Ecrã X a utilizar" -#: src/core/main.c:205 +#: src/core/main.c:213 msgid "Initialize session from savefile" msgstr "Inicializar a sessão a partir de um ficheiro de gravação de sessão" -#: src/core/main.c:211 +#: src/core/main.c:219 msgid "Make X calls synchronous" msgstr "Fazer as chamadas X sincronamente" -#: src/core/main.c:218 +#: src/core/main.c:226 msgid "Run as a wayland compositor" msgstr "Executar como compositor wayland" -#: src/core/main.c:224 +#: src/core/main.c:232 msgid "Run as a nested compositor" msgstr "Executar como compositor aninhado" -#: src/core/main.c:232 +#: src/core/main.c:238 +msgid "Run wayland compositor without starting Xwayland" +msgstr "Executar o compositor wayland sem a utilização do Xwayland" + +#: src/core/main.c:246 msgid "Run as a full display server, rather than nested" msgstr "Executar como servidor de ecrã completo, em vez de aninhado" -#: src/core/mutter.c:39 +#: src/core/main.c:252 +msgid "Run with X11 backend" +msgstr "Executar com a infira-estrutura X11" + +#. Translators: %s is a window title +#: src/core/meta-close-dialog-default.c:151 #, c-format +msgid "“%s” is not responding." +msgstr "“%s” não está a responder." + +#: src/core/meta-close-dialog-default.c:153 +msgid "Application is not responding." +msgstr "A aplicação não está a responder." + +#: src/core/meta-close-dialog-default.c:158 +msgid "" +"You may choose to wait a short while for it to continue or force the " +"application to quit entirely." +msgstr "" +"Poderá aguardar uns instantes para que continue ou forçar a aplicação a " +"terminar definitivamente." + +#: src/core/meta-close-dialog-default.c:165 +msgid "_Force Quit" +msgstr "_Forçar terminar" + +#: src/core/meta-close-dialog-default.c:165 +msgid "_Wait" +msgstr "_Aguardar" + +#: src/core/mutter.c:38 +#, c-format +#| msgid "" +#| "mutter %s\n" +#| "Copyright (C) 2001-%d Havoc Pennington, Red Hat, Inc., and others\n" +#| "This is free software; see the source for copying conditions.\n" +#| "There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A " +#| "PARTICULAR PURPOSE.\n" msgid "" "mutter %s\n" -"Copyright (C) 2001-%d Havoc Pennington, Red Hat, Inc., and others\n" +"Copyright © 2001-%d Havoc Pennington, Red Hat, Inc., and others\n" "This is free software; see the source for copying conditions.\n" "There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A " "PARTICULAR PURPOSE.\n" @@ -580,55 +719,92 @@ "NÃO existe qualquer garantia; nem sequer de COMERCIALIZAÇÃO ou ADEQUAÇÃO A " "UM PROPÓSITO ESPECÍFICO.\n" -#: src/core/mutter.c:53 +#: src/core/mutter.c:52 msgid "Print version" msgstr "Imprimir a versão" -#: src/core/mutter.c:59 +#: src/core/mutter.c:58 msgid "Mutter plugin to use" msgstr "Extensão Mutter a utilizar" -#: src/core/prefs.c:1997 +#: src/core/prefs.c:1911 #, c-format msgid "Workspace %d" msgstr "Área de trabalho %d" -#: src/core/screen.c:521 +#: src/core/util.c:122 +msgid "Mutter was compiled without support for verbose mode\n" +msgstr "O Mutter foi compilado sem suporte para modo verboso\n" + +#: src/wayland/meta-wayland-tablet-pad.c:568 +#, c-format +msgid "Mode Switch: Mode %d" +msgstr "Alteração de Modo: Modo %d" + +#: src/x11/meta-x11-display.c:676 #, c-format +#| msgid "" +#| "Display \"%s\" already has a window manager; try using the --replace " +#| "option to replace the current window manager." msgid "" -"Display \"%s\" already has a window manager; try using the --replace option " -"to replace the current window manager." +"Display “%s” already has a window manager; try using the --replace option to " +"replace the current window manager." msgstr "" -"O ecrã \"%s\" já tem um gestor de janelas; tente utilizar a opção --replace " +"O ecrã “%s” já tem um gestor de janelas; tente utilizar a opção --replace " "para substituir o gestor de janelas atual." -#: src/core/screen.c:606 +#: src/x11/meta-x11-display.c:1089 +msgid "Failed to initialize GDK\n" +msgstr "Falhou ao iniciar o GDK\n" + +#: src/x11/meta-x11-display.c:1113 #, c-format -msgid "Screen %d on display '%s' is invalid\n" -msgstr "Ecrã %d no monitor \"%s\" é inválido\n" +#| msgid "Failed to open X Window System display '%s'\n" +msgid "Failed to open X Window System display “%s”\n" +msgstr "Falha ao abrir ecrã “%s” do sistema Janelas X\n" -#: src/core/util.c:120 -msgid "Mutter was compiled without support for verbose mode\n" -msgstr "O Mutter foi compilado sem suporte para modo verboso\n" +#: src/x11/meta-x11-display.c:1196 +#, c-format +#| msgid "Screen %d on display '%s' is invalid\n" +msgid "Screen %d on display “%s” is invalid\n" +msgstr "Ecrã %d no monitor “%s” é inválido\n" -#: src/wayland/meta-wayland-tablet-pad.c:595 +#: src/x11/meta-x11-selection-input-stream.c:460 #, c-format -msgid "Mode Switch: Mode %d" -msgstr "Alteração de Modo: Modo %d" +msgid "Format %s not supported" +msgstr "O formato “%s” não é suportado" -#: src/x11/session.c:1815 +#: src/x11/session.c:1821 +#| msgid "" +#| "These windows do not support "save current setup" and will have " +#| "to be restarted manually next time you log in." msgid "" -"These windows do not support "save current setup" and will have to " -"be restarted manually next time you log in." +"These windows do not support “save current setup” and will have to be " +"restarted manually next time you log in." msgstr "" -"Estas janelas não suportam "Gravar configuração atual" e terão de " -"ser reiniciadas manualmente da próxima vez que iniciar sessão." +"Estas janelas não suportam “gravar configuração atual” e terão de ser " +"reiniciadas manualmente da próxima vez que iniciar sessão." -#: src/x11/window-props.c:548 +#: src/x11/window-props.c:569 #, c-format msgid "%s (on %s)" msgstr "%s (em %s)" +#~ msgid "Move window one workspace to the left" +#~ msgstr "Mover a janela uma área de trabalho para a esquerda" + +#~ msgid "Move window one workspace to the right" +#~ msgstr "Mover a janela uma área de trabalho para a direita" + +#~ msgid "Move to workspace left" +#~ msgstr "Mover para a área de trabalho à esquerda" + +#~ msgid "Move to workspace right" +#~ msgstr "Mover para a área de trabalho à direita" + +#~ msgid "Toggle shaded state" +#~ msgstr "Alternar estado sombreado" + #~ msgid "background texture could not be created from file" #~ msgstr "incapaz de criar de ficheiro a textura de fundo" @@ -1913,9 +2089,6 @@ #~ msgid "Commands to run in response to keybindings" #~ msgstr "Comandos a executar em resposta a um atalho de teclado" -#~ msgid "Compositing Manager" -#~ msgstr "Gestor de Composições" - #~ msgid "Control how new windows get focus" #~ msgstr "Controla como as novas janelas obtém o foco" diff -Nru mutter-3.36.1/po/sk.po mutter-3.36.9/po/sk.po --- mutter-3.36.1/po/sk.po 2020-03-30 19:29:39.246886300 +0000 +++ mutter-3.36.9/po/sk.po 2021-03-15 23:07:33.230502000 +0000 @@ -13,8 +13,8 @@ msgstr "" "Project-Id-Version: mutter\n" "Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/mutter/issues\n" -"POT-Creation-Date: 2018-02-06 04:14+0000\n" -"PO-Revision-Date: 2018-03-17 21:52+0100\n" +"POT-Creation-Date: 2020-03-30 20:11+0000\n" +"PO-Revision-Date: 2020-04-05 22:21+0200\n" "Last-Translator: Dušan Kazik \n" "Language-Team: Slovak \n" "Language: sk\n" @@ -22,7 +22,7 @@ "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=(n==1) ? 1 : (n>=2 && n<=4) ? 2 : 0;\n" -"X-Generator: Poedit 2.0.6\n" +"X-Generator: Poedit 2.3\n" #: data/50-mutter-navigation.xml:6 msgid "Navigation" @@ -468,29 +468,47 @@ "proof. Currently possible keywords: • “scale-monitor-framebuffer” — makes " "mutter default to layout logical monitors in a logical pixel coordinate " "space, while scaling monitor framebuffers instead of window content, to " -"manage HiDPI monitors. Does not require a restart. • “remote-desktop” — " -"enables remote desktop support. To support remote desktop with screen " -"sharing, “screen-cast” must also be enabled. • “screen-cast” — enables " -"screen cast support." +"manage HiDPI monitors. Does not require a restart. • “rt-scheduler” — makes " +"mutter request a low priority real-time scheduling. The executable or user " +"must have CAP_SYS_NICE. Requires a restart. • “autostart-xwayland” — " +"initializes Xwayland lazily if there are X11 clients. Requires restart." +msgstr "" + +#: data/org.gnome.mutter.gschema.xml.in:134 +msgid "Modifier to use to locate the pointer" +msgstr "Modifikátor použitý na lokalizovanie ukazovateľa" + +#: data/org.gnome.mutter.gschema.xml.in:135 +msgid "This key will initiate the “locate pointer” action." +msgstr "" + +#: data/org.gnome.mutter.gschema.xml.in:142 +msgid "Timeout for check-alive ping" +msgstr "" + +#: data/org.gnome.mutter.gschema.xml.in:143 +msgid "" +"Number of milliseconds a client has to respond to a ping request in order to " +"not be detected as frozen. Using 0 will disable the alive check completely." msgstr "" # summary -#: data/org.gnome.mutter.gschema.xml.in:145 +#: data/org.gnome.mutter.gschema.xml.in:165 msgid "Select window from tab popup" msgstr "Vybrať okno z rozbaľovacej ponuky tabulátora" # summary -#: data/org.gnome.mutter.gschema.xml.in:150 +#: data/org.gnome.mutter.gschema.xml.in:170 msgid "Cancel tab popup" msgstr "Zrušit rozbaľovaciu ponuku tabulátora" # PK: predpokladam ze to prepisane medzi tlacidlami # description -#: data/org.gnome.mutter.gschema.xml.in:155 +#: data/org.gnome.mutter.gschema.xml.in:175 msgid "Switch monitor configurations" msgstr "Prepnúť nastavenia monitorov" -#: data/org.gnome.mutter.gschema.xml.in:160 +#: data/org.gnome.mutter.gschema.xml.in:180 msgid "Rotates the built-in monitor configuration" msgstr "Otočí nastavenie vstavaného monitora" @@ -554,23 +572,27 @@ msgstr "Znovu povoliť klávesové skratky" #: data/org.gnome.mutter.wayland.gschema.xml.in:64 -msgid "Allow grabs with Xwayland" +msgid "Allow X11 grabs to lock keyboard focus with Xwayland" msgstr "" #: data/org.gnome.mutter.wayland.gschema.xml.in:65 msgid "" -"Allow keyboard grabs issued by X11 applications running in Xwayland to be " -"taken into account. For a X11 grab to be taken into account under Wayland, " -"the client must also either send a specific X11 ClientMessage to the root " -"window or be among the applications white-listed in key “xwayland-grab-" -"access-rules”." +"Allow all keyboard events to be routed to X11 “override redirect” windows " +"with a grab when running in Xwayland. This option is to support X11 clients " +"which map an “override redirect” window (which do not receive keyboard " +"focus) and issue a keyboard grab to force all keyboard events to that " +"window. This option is seldom used and has no effect on regular X11 windows " +"which can receive keyboard focus under normal circumstances. For a X11 grab " +"to be taken into account under Wayland, the client must also either send a " +"specific X11 ClientMessage to the root window or be among the applications " +"white-listed in key “xwayland-grab-access-rules”." msgstr "" -#: data/org.gnome.mutter.wayland.gschema.xml.in:77 +#: data/org.gnome.mutter.wayland.gschema.xml.in:84 msgid "Xwayland applications allowed to issue keyboard grabs" msgstr "" -#: data/org.gnome.mutter.wayland.gschema.xml.in:78 +#: data/org.gnome.mutter.wayland.gschema.xml.in:85 msgid "" "List the resource names or resource class of X11 windows either allowed or " "not allowed to issue X11 keyboard grabs under Xwayland. The resource name or " @@ -587,7 +609,7 @@ #. TRANSLATORS: This string refers to a button that switches between #. * different modes. #. -#: src/backends/meta-input-settings.c:2260 +#: src/backends/meta-input-settings.c:2631 #, c-format msgid "Mode Switch (Group %d)" msgstr "Prepínač režimu (skupina č. %d)" @@ -597,53 +619,61 @@ #. TRANSLATORS: This string refers to an action, cycles drawing tablets' #. * mapping through the available outputs. #. -#: src/backends/meta-input-settings.c:2283 +#: src/backends/meta-input-settings.c:2654 msgid "Switch monitor" msgstr "Prepnúť monitor" -#: src/backends/meta-input-settings.c:2285 +#: src/backends/meta-input-settings.c:2656 msgid "Show on-screen help" msgstr "Zobraziť pomocníka na obrazovke" -#: src/backends/meta-monitor-manager.c:900 +#: src/backends/meta-monitor.c:226 msgid "Built-in display" msgstr "Vstavaný displej" -#: src/backends/meta-monitor-manager.c:923 +#: src/backends/meta-monitor.c:255 msgid "Unknown" msgstr "Neznámy" -#: src/backends/meta-monitor-manager.c:925 +#: src/backends/meta-monitor.c:257 msgid "Unknown Display" msgstr "Neznámy displej" -#. TRANSLATORS: this is a monitor vendor name, followed by a -#. * size in inches, like 'Dell 15"' -#. -#: src/backends/meta-monitor-manager.c:933 +#: src/backends/meta-monitor.c:265 #, c-format +#| msgid "%s %s" +msgctxt "" +"This is a monitor vendor name, followed by a size in inches, like 'Dell 15\"'" msgid "%s %s" msgstr "%s %s" +#: src/backends/meta-monitor.c:273 +#, c-format +#| msgid "%s %s" +msgctxt "" +"This is a monitor vendor name followed by product/model name where size in " +"inches could not be calculated, e.g. Dell U2414H" +msgid "%s %s" +msgstr "%s %s" + +#. Translators: this string will appear in Sysprof +#: src/backends/meta-profiler.c:79 +msgid "Compositor" +msgstr "Kompozítor" + #. This probably means that a non-WM compositor like xcompmgr is running; #. * we have no way to get it to exit -#: src/compositor/compositor.c:481 +#: src/compositor/compositor.c:533 #, c-format msgid "" "Another compositing manager is already running on screen %i on display “%s”." msgstr "" "Pre obrazovku č. %i na displeji „%s“ je spustený už iný správca rozloženia." -#: src/core/bell.c:194 +#: src/core/bell.c:192 msgid "Bell event" msgstr "Udalosť zvončeka" -# X window system preloz, napr. system na spravu okien X -#: src/core/display.c:608 -#, c-format -msgid "Failed to open X Window System display “%s”\n" -msgstr "Zlyhalo otvorenie displeja systému na správu okien X „%s“\n" - # cmd desc #: src/core/main.c:190 msgid "Disable connection to session manager" @@ -683,41 +713,45 @@ msgid "Run as a nested compositor" msgstr "Spustí ako kompozitor s vnoreným režimom" -#: src/core/main.c:240 +#: src/core/main.c:238 +msgid "Run wayland compositor without starting Xwayland" +msgstr "" + +#: src/core/main.c:246 msgid "Run as a full display server, rather than nested" msgstr "Spustí ako plnohodnotný zobrazovací server, namiesto vnoreného režimu" -#: src/core/main.c:246 +#: src/core/main.c:252 msgid "Run with X11 backend" msgstr "Spustí s obslužným programom X11" # %s is a window title #. Translators: %s is a window title -#: src/core/meta-close-dialog-default.c:147 +#: src/core/meta-close-dialog-default.c:151 #, c-format msgid "“%s” is not responding." msgstr "„%s“ neodpovedá." -#: src/core/meta-close-dialog-default.c:149 +#: src/core/meta-close-dialog-default.c:153 msgid "Application is not responding." msgstr "Aplikácia neodpovedá." -#: src/core/meta-close-dialog-default.c:154 +#: src/core/meta-close-dialog-default.c:158 msgid "" "You may choose to wait a short while for it to continue or force the " "application to quit entirely." msgstr "" "Môžete chvíľu počkať na pokračovanie aplikácie, alebo ju môžete ukončiť." -#: src/core/meta-close-dialog-default.c:161 +#: src/core/meta-close-dialog-default.c:165 msgid "_Force Quit" msgstr "_Vynútiť ukončenie" -#: src/core/meta-close-dialog-default.c:161 +#: src/core/meta-close-dialog-default.c:165 msgid "_Wait" msgstr "_Počkať" -#: src/core/mutter.c:39 +#: src/core/mutter.c:38 #, c-format msgid "" "mutter %s\n" @@ -733,21 +767,30 @@ "Záruka sa NEPOSKYTUJE; ani na PREDAJNOSŤ alebo VHODNOSŤ PRE URČITÝ ÚČEL.\n" # cmd desc -#: src/core/mutter.c:53 +#: src/core/mutter.c:52 msgid "Print version" msgstr "Zobrazí verziu" # cmd desc -#: src/core/mutter.c:59 +#: src/core/mutter.c:58 msgid "Mutter plugin to use" msgstr "Použije zásuvný modul Mutter" -#: src/core/prefs.c:1997 +#: src/core/prefs.c:1911 #, c-format msgid "Workspace %d" msgstr "Pracovný priestor č. %d" -#: src/core/screen.c:583 +#: src/core/util.c:122 +msgid "Mutter was compiled without support for verbose mode\n" +msgstr "Mutter bol skompilovaný bez výpisu podrobností pri behu\n" + +#: src/wayland/meta-wayland-tablet-pad.c:568 +#, c-format +msgid "Mode Switch: Mode %d" +msgstr "Prepínač režimu: Režim č. %d" + +#: src/x11/meta-x11-display.c:676 #, c-format msgid "" "Display “%s” already has a window manager; try using the --replace option to " @@ -756,21 +799,27 @@ "Displej „%s“ už má správcu okien. Skúste použiť prepínač --replace, aby sa " "aktuálny správca nahradil." -#: src/core/screen.c:668 +#: src/x11/meta-x11-display.c:1089 +msgid "Failed to initialize GDK\n" +msgstr "Zlyhala inicializácia GDK\n" + +# X window system preloz, napr. system na spravu okien X +#: src/x11/meta-x11-display.c:1113 +#, c-format +msgid "Failed to open X Window System display “%s”\n" +msgstr "Zlyhalo otvorenie displeja systému na správu okien X „%s“\n" + +#: src/x11/meta-x11-display.c:1196 #, c-format msgid "Screen %d on display “%s” is invalid\n" msgstr "Obrazovka č. %d na displeji „%s“ nie je platná\n" -#: src/core/util.c:120 -msgid "Mutter was compiled without support for verbose mode\n" -msgstr "Mutter bol skompilovaný bez výpisu podrobností pri behu\n" - -#: src/wayland/meta-wayland-tablet-pad.c:563 +#: src/x11/meta-x11-selection-input-stream.c:460 #, c-format -msgid "Mode Switch: Mode %d" -msgstr "Prepínač režimu: Režim č. %d" +msgid "Format %s not supported" +msgstr "Formát %s nie je podporovaný" -#: src/x11/session.c:1818 +#: src/x11/session.c:1821 msgid "" "These windows do not support “save current setup” and will have to be " "restarted manually next time you log in." @@ -779,7 +828,7 @@ "prihlásení ich budete musieť znovu spustiť ručne." # window title; wm_client_machine -#: src/x11/window-props.c:559 +#: src/x11/window-props.c:569 #, c-format msgid "%s (on %s)" msgstr "%s (na %s)" diff -Nru mutter-3.36.1/src/backends/meta-backend.c mutter-3.36.9/src/backends/meta-backend.c --- mutter-3.36.1/src/backends/meta-backend.c 2020-03-30 19:29:39.261886000 +0000 +++ mutter-3.36.9/src/backends/meta-backend.c 2021-03-15 23:07:33.251501300 +0000 @@ -81,6 +81,10 @@ #include "backends/native/meta-backend-native.h" #endif +#ifdef HAVE_WAYLAND +#include "wayland/meta-wayland.h" +#endif + enum { KEYMAP_CHANGED, @@ -130,6 +134,10 @@ MetaRemoteDesktop *remote_desktop; #endif +#ifdef HAVE_WAYLAND + MetaWaylandCompositor *wayland_compositor; +#endif + #ifdef HAVE_PROFILER MetaProfiler *profiler; #endif @@ -193,6 +201,7 @@ g_list_free_full (priv->gpus, g_object_unref); + g_clear_object (&priv->current_device); g_clear_object (&priv->monitor_manager); g_clear_object (&priv->orientation_manager); g_clear_object (&priv->input_settings); @@ -356,16 +365,6 @@ create_device_monitor (backend, device); } -static void -on_device_added (ClutterSeat *seat, - ClutterInputDevice *device, - gpointer user_data) -{ - MetaBackend *backend = META_BACKEND (user_data); - - create_device_monitor (backend, device); -} - static inline gboolean device_is_slave_touchscreen (ClutterInputDevice *device) { @@ -426,6 +425,20 @@ } static void +on_device_added (ClutterSeat *seat, + ClutterInputDevice *device, + gpointer user_data) +{ + MetaBackend *backend = META_BACKEND (user_data); + MetaBackendPrivate *priv = meta_backend_get_instance_private (backend); + + create_device_monitor (backend, device); + + if (device_is_slave_touchscreen (device)) + meta_cursor_tracker_set_pointer_visible (priv->cursor_tracker, FALSE); +} + +static void on_device_removed (ClutterSeat *seat, ClutterInputDevice *device, gpointer user_data) @@ -444,7 +457,8 @@ gboolean has_touchscreen, has_pointing_device; ClutterInputDeviceType device_type; - priv->current_device = NULL; + g_clear_object (&priv->current_device); + g_clear_handle_id (&priv->device_update_idle_id, g_source_remove); device_type = clutter_input_device_get_device_type (device); has_touchscreen = check_has_slave_touchscreen (seat); @@ -462,6 +476,9 @@ !has_touchscreen); } } + + if (priv->current_device == device) + meta_backend_update_last_device (backend, NULL); } static void @@ -484,27 +501,6 @@ g_list_free (devices); } -static void -set_initial_pointer_visibility (MetaBackend *backend, - ClutterSeat *seat) -{ - MetaBackendPrivate *priv = meta_backend_get_instance_private (backend); - GList *l, *devices; - gboolean has_touchscreen = FALSE; - - devices = clutter_seat_list_devices (seat); - for (l = devices; l; l = l->next) - { - ClutterInputDevice *device = l->data; - - has_touchscreen |= device_is_slave_touchscreen (device); - } - - g_list_free (devices); - meta_cursor_tracker_set_pointer_visible (priv->cursor_tracker, - !has_touchscreen); -} - static MetaInputSettings * meta_backend_create_input_settings (MetaBackend *backend) { @@ -536,9 +532,8 @@ g_signal_connect_object (seat, "device-added", G_CALLBACK (on_device_added), backend, 0); g_signal_connect_object (seat, "device-removed", - G_CALLBACK (on_device_removed), backend, 0); - - set_initial_pointer_visibility (backend, seat); + G_CALLBACK (on_device_removed), backend, + G_CONNECT_AFTER); priv->input_settings = meta_backend_create_input_settings (backend); @@ -867,6 +862,120 @@ NULL); } +#ifdef HAVE_WAYLAND +MetaWaylandCompositor * +meta_backend_get_wayland_compositor (MetaBackend *backend) +{ + MetaBackendPrivate *priv = meta_backend_get_instance_private (backend); + + return priv->wayland_compositor; +} + +void +meta_backend_init_wayland_display (MetaBackend *backend) +{ + MetaBackendPrivate *priv = meta_backend_get_instance_private (backend); + + priv->wayland_compositor = meta_wayland_compositor_new (backend); +} + +void +meta_backend_init_wayland (MetaBackend *backend) +{ + MetaBackendPrivate *priv = meta_backend_get_instance_private (backend); + + meta_wayland_compositor_setup (priv->wayland_compositor); +} +#endif + +/* Mutter is responsible for pulling events off the X queue, so Clutter + * doesn't need (and shouldn't) run its normal event source which polls + * the X fd, but we do have to deal with dispatching events that accumulate + * in the clutter queue. This happens, for example, when clutter generate + * enter/leave events on mouse motion - several events are queued in the + * clutter queue but only one dispatched. It could also happen because of + * explicit calls to clutter_event_put(). We add a very simple custom + * event loop source which is simply responsible for pulling events off + * of the queue and dispatching them before we block for new events. + */ + +static gboolean +clutter_source_prepare (GSource *source, + int *timeout) +{ + *timeout = -1; + + return clutter_events_pending (); +} + +static gboolean +clutter_source_check (GSource *source) +{ + return clutter_events_pending (); +} + +static gboolean +clutter_source_dispatch (GSource *source, + GSourceFunc callback, + gpointer user_data) +{ + ClutterEvent *event = clutter_event_get (); + + if (event) + { + clutter_do_event (event); + clutter_event_free (event); + } + + return TRUE; +} + +static GSourceFuncs clutter_source_funcs = { + clutter_source_prepare, + clutter_source_check, + clutter_source_dispatch +}; + +static ClutterBackend * +meta_get_clutter_backend (void) +{ + MetaBackend *backend = meta_get_backend (); + + return meta_backend_get_clutter_backend (backend); +} + +static gboolean +init_clutter (MetaBackend *backend, + GError **error) +{ + GSource *source; + + clutter_set_custom_backend_func (meta_get_clutter_backend); + + if (clutter_init (NULL, NULL) != CLUTTER_INIT_SUCCESS) + { + g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, + "Unable to initialize Clutter"); + return FALSE; + } + + source = g_source_new (&clutter_source_funcs, sizeof (GSource)); + g_source_attach (source, NULL); + g_source_unref (source); + + return TRUE; +} + +static void +meta_backend_post_init (MetaBackend *backend) +{ + MetaBackendPrivate *priv = meta_backend_get_instance_private (backend); + + META_BACKEND_GET_CLASS (backend)->post_init (backend); + + meta_settings_post_init (priv->settings); +} + static gboolean meta_backend_initable_init (GInitable *initable, GCancellable *cancellable, @@ -905,6 +1014,11 @@ priv->profiler = meta_profiler_new (); #endif + if (!init_clutter (backend, error)) + return FALSE; + + meta_backend_post_init (backend); + return TRUE; } @@ -920,16 +1034,6 @@ _backend = backend; } -static void -meta_backend_post_init (MetaBackend *backend) -{ - MetaBackendPrivate *priv = meta_backend_get_instance_private (backend); - - META_BACKEND_GET_CLASS (backend)->post_init (backend); - - meta_settings_post_init (priv->settings); -} - /** * meta_backend_get_idle_monitor: (skip) */ @@ -1220,7 +1324,7 @@ clutter_input_device_get_device_mode (device) == CLUTTER_INPUT_MODE_MASTER) return; - priv->current_device = device; + g_set_object (&priv->current_device, device); if (priv->device_update_idle_id == 0) { @@ -1261,54 +1365,6 @@ priv->client_pointer_constraint = g_object_ref (constraint); } -/* Mutter is responsible for pulling events off the X queue, so Clutter - * doesn't need (and shouldn't) run its normal event source which polls - * the X fd, but we do have to deal with dispatching events that accumulate - * in the clutter queue. This happens, for example, when clutter generate - * enter/leave events on mouse motion - several events are queued in the - * clutter queue but only one dispatched. It could also happen because of - * explicit calls to clutter_event_put(). We add a very simple custom - * event loop source which is simply responsible for pulling events off - * of the queue and dispatching them before we block for new events. - */ - -static gboolean -event_prepare (GSource *source, - gint *timeout_) -{ - *timeout_ = -1; - - return clutter_events_pending (); -} - -static gboolean -event_check (GSource *source) -{ - return clutter_events_pending (); -} - -static gboolean -event_dispatch (GSource *source, - GSourceFunc callback, - gpointer user_data) -{ - ClutterEvent *event = clutter_event_get (); - - if (event) - { - clutter_do_event (event); - clutter_event_free (event); - } - - return TRUE; -} - -static GSourceFuncs event_funcs = { - event_prepare, - event_check, - event_dispatch -}; - ClutterBackend * meta_backend_get_clutter_backend (MetaBackend *backend) { @@ -1323,14 +1379,6 @@ return priv->clutter_backend; } -static ClutterBackend * -meta_get_clutter_backend (void) -{ - MetaBackend *backend = meta_get_backend (); - - return meta_backend_get_clutter_backend (backend); -} - void meta_init_backend (GType backend_gtype) { @@ -1348,29 +1396,6 @@ } /** - * meta_clutter_init: (skip) - */ -void -meta_clutter_init (void) -{ - GSource *source; - - clutter_set_custom_backend_func (meta_get_clutter_backend); - - if (clutter_init (NULL, NULL) != CLUTTER_INIT_SUCCESS) - { - g_warning ("Unable to initialize Clutter.\n"); - exit (1); - } - - source = g_source_new (&event_funcs, sizeof (GSource)); - g_source_attach (source, NULL); - g_source_unref (source); - - meta_backend_post_init (_backend); -} - -/** * meta_is_stage_views_enabled: * * Returns whether the #ClutterStage can be rendered using multiple stage views. diff -Nru mutter-3.36.1/src/backends/meta-backend-private.h mutter-3.36.9/src/backends/meta-backend-private.h --- mutter-3.36.1/src/backends/meta-backend-private.h 2020-03-30 19:29:39.260886000 +0000 +++ mutter-3.36.9/src/backends/meta-backend-private.h 2021-03-15 23:07:33.250501400 +0000 @@ -108,6 +108,14 @@ void meta_init_backend (GType backend_gtype); +#ifdef HAVE_WAYLAND +MetaWaylandCompositor * meta_backend_get_wayland_compositor (MetaBackend *backend); + +void meta_backend_init_wayland_display (MetaBackend *backend); + +void meta_backend_init_wayland (MetaBackend *backend); +#endif + ClutterBackend * meta_backend_get_clutter_backend (MetaBackend *backend); MetaIdleMonitor * meta_backend_get_idle_monitor (MetaBackend *backend, diff -Nru mutter-3.36.1/src/backends/meta-backend-types.h mutter-3.36.9/src/backends/meta-backend-types.h --- mutter-3.36.1/src/backends/meta-backend-types.h 2020-03-30 19:29:39.260886000 +0000 +++ mutter-3.36.9/src/backends/meta-backend-types.h 2021-03-15 23:07:33.250501400 +0000 @@ -53,4 +53,6 @@ typedef struct _MetaScreenCastSession MetaScreenCastSession; typedef struct _MetaScreenCastStream MetaScreenCastStream; +typedef struct _MetaWaylandCompositor MetaWaylandCompositor; + #endif /* META_BACKEND_TYPE_H */ diff -Nru mutter-3.36.1/src/backends/meta-barrier.c mutter-3.36.9/src/backends/meta-barrier.c --- mutter-3.36.1/src/backends/meta-barrier.c 2020-03-30 19:29:39.261886000 +0000 +++ mutter-3.36.9/src/backends/meta-barrier.c 2021-03-15 23:07:33.251501300 +0000 @@ -128,6 +128,7 @@ meta_barrier_dispose (GObject *object) { MetaBarrier *barrier = META_BARRIER (object); + MetaBarrierPrivate *priv = barrier->priv; if (meta_barrier_is_active (barrier)) { @@ -135,6 +136,8 @@ barrier); } + g_clear_object (&priv->impl); + G_OBJECT_CLASS (meta_barrier_parent_class)->dispose (object); } @@ -294,7 +297,7 @@ MetaBarrierImpl *impl = barrier->priv->impl; if (impl) - return META_BARRIER_IMPL_GET_CLASS (impl)->destroy (impl); + META_BARRIER_IMPL_GET_CLASS (impl)->destroy (impl); g_object_unref (barrier); } diff -Nru mutter-3.36.1/src/backends/meta-cursor-sprite-xcursor.c mutter-3.36.9/src/backends/meta-cursor-sprite-xcursor.c --- mutter-3.36.1/src/backends/meta-cursor-sprite-xcursor.c 2020-03-30 19:29:39.261886000 +0000 +++ mutter-3.36.9/src/backends/meta-cursor-sprite-xcursor.c 2021-03-15 23:07:33.252501200 +0000 @@ -109,9 +109,26 @@ static XcursorImages * load_cursor_on_client (MetaCursor cursor, int scale) { - return XcursorLibraryLoadImages (translate_meta_cursor (cursor), - meta_prefs_get_cursor_theme (), - meta_prefs_get_cursor_size () * scale); + XcursorImages *xcursor_images; + int fallback_size; + + xcursor_images = + XcursorLibraryLoadImages (translate_meta_cursor (cursor), + meta_prefs_get_cursor_theme (), + meta_prefs_get_cursor_size () * scale); + if (xcursor_images) + return xcursor_images; + + g_warning ("No cursor theme available, please install a cursor theme"); + + fallback_size = 24 * scale; + xcursor_images = XcursorImagesCreate (1); + xcursor_images->images[0] = XcursorImageCreate (fallback_size, fallback_size); + xcursor_images->images[0]->xhot = 0; + xcursor_images->images[0]->yhot = 0; + memset (xcursor_images->images[0]->pixels, 0xc0, + fallback_size * fallback_size * sizeof (int32_t)); + return xcursor_images; } static void @@ -246,8 +263,6 @@ sprite_xcursor->xcursor_images = load_cursor_on_client (sprite_xcursor->cursor, sprite_xcursor->theme_scale); - if (!sprite_xcursor->xcursor_images) - g_error ("Could not find cursor. Perhaps set XCURSOR_PATH?"); load_from_current_xcursor_image (sprite_xcursor); } diff -Nru mutter-3.36.1/src/backends/meta-input-settings.c mutter-3.36.9/src/backends/meta-input-settings.c --- mutter-3.36.1/src/backends/meta-input-settings.c 2020-03-30 19:29:39.265885800 +0000 +++ mutter-3.36.9/src/backends/meta-input-settings.c 2021-03-15 23:07:33.257501100 +0000 @@ -818,7 +818,7 @@ for (l = devices; l; l = l->next) { - device = devices->data; + device = l->data; if (input_settings_class->is_trackball_device (input_settings, device)) input_settings_class->set_scroll_button (input_settings, device, button); diff -Nru mutter-3.36.1/src/backends/meta-monitor.c mutter-3.36.9/src/backends/meta-monitor.c --- mutter-3.36.1/src/backends/meta-monitor.c 2020-03-30 19:29:39.268885900 +0000 +++ mutter-3.36.9/src/backends/meta-monitor.c 2021-03-15 23:07:33.261501000 +0000 @@ -817,19 +817,19 @@ case META_MONITOR_TRANSFORM_270: case META_MONITOR_TRANSFORM_FLIPPED_270: if (other_output->tile_info.loc_v_tile == output->tile_info.loc_v_tile && - other_output->tile_info.loc_h_tile < output->tile_info.loc_h_tile) + other_output->tile_info.loc_h_tile > output->tile_info.loc_h_tile) y += other_output->tile_info.tile_w; if (other_output->tile_info.loc_h_tile == output->tile_info.loc_h_tile && - other_output->tile_info.loc_v_tile < output->tile_info.loc_v_tile) + other_output->tile_info.loc_v_tile > output->tile_info.loc_v_tile) x += other_output->tile_info.tile_h; break; case META_MONITOR_TRANSFORM_90: case META_MONITOR_TRANSFORM_FLIPPED_90: if (other_output->tile_info.loc_v_tile == output->tile_info.loc_v_tile && - other_output->tile_info.loc_h_tile > output->tile_info.loc_h_tile) + other_output->tile_info.loc_h_tile < output->tile_info.loc_h_tile) y += other_output->tile_info.tile_w; if (other_output->tile_info.loc_h_tile == output->tile_info.loc_h_tile && - other_output->tile_info.loc_v_tile > output->tile_info.loc_v_tile) + other_output->tile_info.loc_v_tile < output->tile_info.loc_v_tile) x += other_output->tile_info.tile_h; break; } diff -Nru mutter-3.36.1/src/backends/meta-monitor-config-manager.c mutter-3.36.9/src/backends/meta-monitor-config-manager.c --- mutter-3.36.1/src/backends/meta-monitor-config-manager.c 2020-03-30 19:29:39.266885800 +0000 +++ mutter-3.36.9/src/backends/meta-monitor-config-manager.c 2021-03-15 23:07:33.258501000 +0000 @@ -172,6 +172,7 @@ MetaCrtc *crtc; MetaMonitorTransform transform; MetaMonitorTransform crtc_transform; + MetaMonitorTransform crtc_hw_transform; int crtc_x, crtc_y; float x_offset, y_offset; float scale = 0.0; @@ -200,10 +201,12 @@ transform = data->logical_monitor_config->transform; crtc_transform = meta_monitor_logical_to_crtc_transform (monitor, transform); - if (!meta_monitor_manager_is_transform_handled (data->monitor_manager, - crtc, - crtc_transform)) - crtc_transform = META_MONITOR_TRANSFORM_NORMAL; + if (meta_monitor_manager_is_transform_handled (data->monitor_manager, + crtc, + crtc_transform)) + crtc_hw_transform = crtc_transform; + else + crtc_hw_transform = META_MONITOR_TRANSFORM_NORMAL; meta_monitor_calculate_crtc_pos (monitor, mode, output, crtc_transform, &crtc_x, &crtc_y); @@ -244,7 +247,7 @@ .crtc = crtc, .mode = crtc_mode, .layout = crtc_layout, - .transform = crtc_transform, + .transform = crtc_hw_transform, .outputs = g_ptr_array_new () }; g_ptr_array_add (crtc_info->outputs, output); @@ -443,23 +446,35 @@ meta_create_monitors_config_key_for_current_state (MetaMonitorManager *monitor_manager) { MetaMonitorsConfigKey *config_key; + MetaMonitorSpec *laptop_monitor_spec; GList *l; GList *monitor_specs; + laptop_monitor_spec = NULL; monitor_specs = NULL; for (l = monitor_manager->monitors; l; l = l->next) { MetaMonitor *monitor = l->data; MetaMonitorSpec *monitor_spec; - if (meta_monitor_is_laptop_panel (monitor) && - is_lid_closed (monitor_manager)) - continue; + if (meta_monitor_is_laptop_panel (monitor)) + { + laptop_monitor_spec = meta_monitor_get_spec (monitor); + + if (is_lid_closed (monitor_manager)) + continue; + } monitor_spec = meta_monitor_spec_clone (meta_monitor_get_spec (monitor)); monitor_specs = g_list_prepend (monitor_specs, monitor_spec); } + if (!monitor_specs && laptop_monitor_spec) + { + monitor_specs = + g_list_prepend (NULL, meta_monitor_spec_clone (laptop_monitor_spec)); + } + if (!monitor_specs) return NULL; diff -Nru mutter-3.36.1/src/backends/meta-remote-desktop-session.c mutter-3.36.9/src/backends/meta-remote-desktop-session.c --- mutter-3.36.1/src/backends/meta-remote-desktop-session.c 2020-03-30 19:29:39.270885700 +0000 +++ mutter-3.36.9/src/backends/meta-remote-desktop-session.c 2021-03-15 23:07:33.262501000 +0000 @@ -55,6 +55,7 @@ MetaScreenCastSession *screen_cast_session; gulong screen_cast_session_closed_handler_id; + guint started : 1; ClutterVirtualInputDevice *virtual_pointer; ClutterVirtualInputDevice *virtual_keyboard; @@ -119,7 +120,7 @@ ClutterBackend *backend = clutter_get_default_backend (); ClutterSeat *seat = clutter_backend_get_default_seat (backend); - g_assert (!session->virtual_pointer && !session->virtual_keyboard); + g_assert (!session->started); if (session->screen_cast_session) { @@ -135,6 +136,7 @@ clutter_seat_create_virtual_device (seat, CLUTTER_TOUCHSCREEN_DEVICE); init_remote_access_handle (session); + session->started = TRUE; return TRUE; } @@ -145,6 +147,8 @@ MetaDBusRemoteDesktopSession *skeleton = META_DBUS_REMOTE_DESKTOP_SESSION (session); + session->started = FALSE; + if (session->screen_cast_session) { g_clear_signal_handler (&session->screen_cast_session_closed_handler_id, @@ -250,12 +254,43 @@ } static gboolean +meta_remote_desktop_session_check_can_notify (MetaRemoteDesktopSession *session, + GDBusMethodInvocation *invocation) +{ + if (!session->started) + { + g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, + G_DBUS_ERROR_FAILED, + "Session not started"); + return FALSE; + } + + if (!check_permission (session, invocation)) + { + g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, + G_DBUS_ERROR_ACCESS_DENIED, + "Permission denied"); + return FALSE; + } + + return TRUE; +} + +static gboolean handle_start (MetaDBusRemoteDesktopSession *skeleton, GDBusMethodInvocation *invocation) { MetaRemoteDesktopSession *session = META_REMOTE_DESKTOP_SESSION (skeleton); GError *error = NULL; + if (session->started) + { + g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, + G_DBUS_ERROR_FAILED, + "Already started"); + return TRUE; + } + if (!check_permission (session, invocation)) { g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, @@ -288,6 +323,14 @@ { MetaRemoteDesktopSession *session = META_REMOTE_DESKTOP_SESSION (skeleton); + if (!session->started) + { + g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, + G_DBUS_ERROR_FAILED, + "Session not started"); + return TRUE; + } + if (!check_permission (session, invocation)) { g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, @@ -312,13 +355,8 @@ MetaRemoteDesktopSession *session = META_REMOTE_DESKTOP_SESSION (skeleton); ClutterKeyState state; - if (!check_permission (session, invocation)) - { - g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, - G_DBUS_ERROR_ACCESS_DENIED, - "Permission denied"); - return TRUE; - } + if (!meta_remote_desktop_session_check_can_notify (session, invocation)) + return TRUE; if (pressed) state = CLUTTER_KEY_STATE_PRESSED; @@ -344,13 +382,8 @@ MetaRemoteDesktopSession *session = META_REMOTE_DESKTOP_SESSION (skeleton); ClutterKeyState state; - if (!check_permission (session, invocation)) - { - g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, - G_DBUS_ERROR_ACCESS_DENIED, - "Permission denied"); - return TRUE; - } + if (!meta_remote_desktop_session_check_can_notify (session, invocation)) + return TRUE; if (pressed) state = CLUTTER_KEY_STATE_PRESSED; @@ -398,13 +431,8 @@ uint32_t button; ClutterButtonState state; - if (!check_permission (session, invocation)) - { - g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, - G_DBUS_ERROR_ACCESS_DENIED, - "Permission denied"); - return TRUE; - } + if (!meta_remote_desktop_session_check_can_notify (session, invocation)) + return TRUE; button = translate_to_clutter_button (button_code); @@ -434,13 +462,8 @@ MetaRemoteDesktopSession *session = META_REMOTE_DESKTOP_SESSION (skeleton); ClutterScrollFinishFlags finish_flags = CLUTTER_SCROLL_FINISHED_NONE; - if (!check_permission (session, invocation)) - { - g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, - G_DBUS_ERROR_ACCESS_DENIED, - "Permission denied"); - return TRUE; - } + if (!meta_remote_desktop_session_check_can_notify (session, invocation)) + return TRUE; if (flags & META_REMOTE_DESKTOP_NOTIFY_AXIS_FLAGS_FINISH) { @@ -487,13 +510,8 @@ ClutterScrollDirection direction; int step_count; - if (!check_permission (session, invocation)) - { - g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, - G_DBUS_ERROR_ACCESS_DENIED, - "Permission denied"); - return TRUE; - } + if (!meta_remote_desktop_session_check_can_notify (session, invocation)) + return TRUE; if (axis > 1) { @@ -538,13 +556,8 @@ { MetaRemoteDesktopSession *session = META_REMOTE_DESKTOP_SESSION (skeleton); - if (!check_permission (session, invocation)) - { - g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, - G_DBUS_ERROR_ACCESS_DENIED, - "Permission denied"); - return TRUE; - } + if (!meta_remote_desktop_session_check_can_notify (session, invocation)) + return TRUE; clutter_virtual_input_device_notify_relative_motion (session->virtual_pointer, CLUTTER_CURRENT_TIME, @@ -567,13 +580,9 @@ MetaScreenCastStream *stream; double abs_x, abs_y; - if (!check_permission (session, invocation)) - { - g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, - G_DBUS_ERROR_ACCESS_DENIED, - "Permission denied"); - return TRUE; - } + if (!meta_remote_desktop_session_check_can_notify (session, invocation)) + return TRUE; + if (!session->screen_cast_session) { @@ -617,13 +626,8 @@ MetaScreenCastStream *stream; double abs_x, abs_y; - if (!check_permission (session, invocation)) - { - g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, - G_DBUS_ERROR_ACCESS_DENIED, - "Permission denied"); - return TRUE; - } + if (!meta_remote_desktop_session_check_can_notify (session, invocation)) + return TRUE; if (!session->screen_cast_session) { @@ -668,13 +672,9 @@ MetaScreenCastStream *stream; double abs_x, abs_y; - if (!check_permission (session, invocation)) - { - g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, - G_DBUS_ERROR_ACCESS_DENIED, - "Permission denied"); - return TRUE; - } + if (!meta_remote_desktop_session_check_can_notify (session, invocation)) + return TRUE; + if (!session->screen_cast_session) { @@ -714,13 +714,8 @@ { MetaRemoteDesktopSession *session = META_REMOTE_DESKTOP_SESSION (skeleton); - if (!check_permission (session, invocation)) - { - g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, - G_DBUS_ERROR_ACCESS_DENIED, - "Permission denied"); - return TRUE; - } + if (!meta_remote_desktop_session_check_can_notify (session, invocation)) + return TRUE; clutter_virtual_input_device_notify_touch_up (session->virtual_touchscreen, CLUTTER_CURRENT_TIME, diff -Nru mutter-3.36.1/src/backends/meta-renderer.c mutter-3.36.9/src/backends/meta-renderer.c --- mutter-3.36.1/src/backends/meta-renderer.c 2020-03-30 19:29:39.270885700 +0000 +++ mutter-3.36.9/src/backends/meta-renderer.c 2021-03-15 23:07:33.263501000 +0000 @@ -160,14 +160,12 @@ } void -meta_renderer_set_legacy_view (MetaRenderer *renderer, - MetaRendererView *legacy_view) +meta_renderer_add_view (MetaRenderer *renderer, + MetaRendererView *view) { MetaRendererPrivate *priv = meta_renderer_get_instance_private (renderer); - g_assert (!priv->views); - - priv->views = g_list_append (priv->views, legacy_view); + priv->views = g_list_append (priv->views, view); } /** diff -Nru mutter-3.36.1/src/backends/meta-renderer.h mutter-3.36.9/src/backends/meta-renderer.h --- mutter-3.36.1/src/backends/meta-renderer.h 2020-03-30 19:29:39.270885700 +0000 +++ mutter-3.36.9/src/backends/meta-renderer.h 2021-03-15 23:07:33.263501000 +0000 @@ -54,8 +54,8 @@ void meta_renderer_rebuild_views (MetaRenderer *renderer); -void meta_renderer_set_legacy_view (MetaRenderer *renderer, - MetaRendererView *legacy_view); +void meta_renderer_add_view (MetaRenderer *renderer, + MetaRendererView *view); META_EXPORT_TEST GList * meta_renderer_get_views (MetaRenderer *renderer); diff -Nru mutter-3.36.1/src/backends/meta-screen-cast-monitor-stream-src.c mutter-3.36.9/src/backends/meta-screen-cast-monitor-stream-src.c --- mutter-3.36.1/src/backends/meta-screen-cast-monitor-stream-src.c 2020-03-30 19:29:39.270885700 +0000 +++ mutter-3.36.9/src/backends/meta-screen-cast-monitor-stream-src.c 2021-03-15 23:07:33.264500900 +0000 @@ -115,13 +115,16 @@ } static void -stage_painted (MetaStage *stage, - ClutterStageView *view, - gpointer user_data) +stage_painted (MetaStage *stage, + ClutterStageView *view, + ClutterPaintContext *paint_context, + gpointer user_data) { MetaScreenCastStreamSrc *src = META_SCREEN_CAST_STREAM_SRC (user_data); + MetaScreenCastRecordFlag flags; - meta_screen_cast_stream_src_maybe_record_frame (src); + flags = META_SCREEN_CAST_RECORD_FLAG_NONE; + meta_screen_cast_stream_src_maybe_record_frame (src, flags); } static MetaBackend * @@ -180,14 +183,16 @@ { MetaScreenCastStreamSrc *src = META_SCREEN_CAST_STREAM_SRC (monitor_src); ClutterStage *stage = get_stage (monitor_src); + MetaScreenCastRecordFlag flags; - if (!is_cursor_in_stream (monitor_src)) + if (clutter_stage_is_redraw_queued (stage)) return; - if (clutter_stage_is_redraw_queued (stage)) + if (meta_screen_cast_stream_src_pending_follow_up_frame (src)) return; - meta_screen_cast_stream_src_maybe_record_frame (src); + flags = META_SCREEN_CAST_RECORD_FLAG_CURSOR_ONLY; + meta_screen_cast_stream_src_maybe_record_frame (src, flags); } static void @@ -361,8 +366,9 @@ } static gboolean -meta_screen_cast_monitor_stream_src_record_frame (MetaScreenCastStreamSrc *src, - uint8_t *data) +meta_screen_cast_monitor_stream_src_record_to_buffer (MetaScreenCastStreamSrc *src, + uint8_t *data, + GError **error) { MetaScreenCastMonitorStreamSrc *monitor_src = META_SCREEN_CAST_MONITOR_STREAM_SRC (src); @@ -371,9 +377,6 @@ MetaLogicalMonitor *logical_monitor; stage = get_stage (monitor_src); - if (!clutter_stage_is_redraw_queued (stage)) - return FALSE; - monitor = get_monitor (monitor_src); logical_monitor = meta_monitor_get_logical_monitor (monitor); clutter_stage_capture_into (stage, FALSE, &logical_monitor->rect, data); @@ -382,8 +385,9 @@ } static gboolean -meta_screen_cast_monitor_stream_src_blit_to_framebuffer (MetaScreenCastStreamSrc *src, - CoglFramebuffer *framebuffer) +meta_screen_cast_monitor_stream_src_record_to_framebuffer (MetaScreenCastStreamSrc *src, + CoglFramebuffer *framebuffer, + GError **error) { MetaScreenCastMonitorStreamSrc *monitor_src = META_SCREEN_CAST_MONITOR_STREAM_SRC (src); @@ -407,7 +411,6 @@ for (l = meta_renderer_get_views (renderer); l; l = l->next) { ClutterStageView *view = CLUTTER_STAGE_VIEW (l->data); - g_autoptr (GError) error = NULL; CoglFramebuffer *view_framebuffer; MetaRectangle view_layout; int x, y; @@ -428,12 +431,8 @@ x, y, cogl_framebuffer_get_width (view_framebuffer), cogl_framebuffer_get_height (view_framebuffer), - &error)) - { - g_warning ("Error blitting view into DMABuf framebuffer: %s", - error->message); - return FALSE; - } + error)) + return FALSE; } cogl_framebuffer_finish (framebuffer); @@ -442,6 +441,44 @@ } static void +meta_screen_cast_monitor_stream_record_follow_up (MetaScreenCastStreamSrc *src) +{ + MetaScreenCastMonitorStreamSrc *monitor_src = + META_SCREEN_CAST_MONITOR_STREAM_SRC (src); + MetaBackend *backend = get_backend (monitor_src); + MetaRenderer *renderer = meta_backend_get_renderer (backend); + ClutterStage *stage = get_stage (monitor_src); + MetaMonitor *monitor; + MetaLogicalMonitor *logical_monitor; + MetaRectangle logical_monitor_layout; + GList *l; + + monitor = get_monitor (monitor_src); + logical_monitor = meta_monitor_get_logical_monitor (monitor); + logical_monitor_layout = meta_logical_monitor_get_layout (logical_monitor); + + for (l = meta_renderer_get_views (renderer); l; l = l->next) + { + MetaRendererView *view = l->data; + MetaRectangle view_layout; + MetaRectangle damage; + + clutter_stage_view_get_layout (CLUTTER_STAGE_VIEW (view), &view_layout); + + if (!meta_rectangle_overlap (&logical_monitor_layout, &view_layout)) + continue; + + damage = (cairo_rectangle_int_t) { + .x = view_layout.x, + .y = view_layout.y, + .width = 1, + .height = 1, + }; + clutter_actor_queue_redraw_with_clip (CLUTTER_ACTOR (stage), &damage); + } +} + +static void meta_screen_cast_monitor_stream_src_set_cursor_metadata (MetaScreenCastStreamSrc *src, struct spa_meta_cursor *spa_meta_cursor) { @@ -561,9 +598,12 @@ src_class->get_specs = meta_screen_cast_monitor_stream_src_get_specs; src_class->enable = meta_screen_cast_monitor_stream_src_enable; src_class->disable = meta_screen_cast_monitor_stream_src_disable; - src_class->record_frame = meta_screen_cast_monitor_stream_src_record_frame; - src_class->blit_to_framebuffer = - meta_screen_cast_monitor_stream_src_blit_to_framebuffer; + src_class->record_to_buffer = + meta_screen_cast_monitor_stream_src_record_to_buffer; + src_class->record_to_framebuffer = + meta_screen_cast_monitor_stream_src_record_to_framebuffer; + src_class->record_follow_up = + meta_screen_cast_monitor_stream_record_follow_up; src_class->set_cursor_metadata = meta_screen_cast_monitor_stream_src_set_cursor_metadata; } diff -Nru mutter-3.36.1/src/backends/meta-screen-cast-stream-src.c mutter-3.36.9/src/backends/meta-screen-cast-stream-src.c --- mutter-3.36.1/src/backends/meta-screen-cast-stream-src.c 2020-03-30 19:29:39.271885900 +0000 +++ mutter-3.36.9/src/backends/meta-screen-cast-stream-src.c 2021-03-15 23:07:33.265501000 +0000 @@ -68,6 +68,7 @@ { GSource base; + MetaScreenCastStreamSrc *src; struct pw_loop *pipewire_loop; } MetaPipeWireSource; @@ -81,6 +82,7 @@ struct spa_hook pipewire_core_listener; gboolean is_enabled; + gboolean emit_closed_after_dispatch; struct pw_stream *pipewire_stream; struct spa_hook pipewire_stream_listener; @@ -89,7 +91,8 @@ struct spa_video_info_raw video_format; int video_stride; - uint64_t last_frame_timestamp_us; + int64_t last_frame_timestamp_us; + guint follow_up_frame_source_id; GHashTable *dmabuf_handles; @@ -107,6 +110,12 @@ meta_screen_cast_stream_src_init_initable_iface) G_ADD_PRIVATE (MetaScreenCastStreamSrc)) +static inline uint32_t +us2ms (uint64_t us) +{ + return (uint32_t) (us / 1000); +} + static void meta_screen_cast_stream_src_get_specs (MetaScreenCastStreamSrc *src, int *width, @@ -133,23 +142,34 @@ } static gboolean -meta_screen_cast_stream_src_record_frame (MetaScreenCastStreamSrc *src, - uint8_t *data) +meta_screen_cast_stream_src_record_to_buffer (MetaScreenCastStreamSrc *src, + uint8_t *data, + GError **error) { MetaScreenCastStreamSrcClass *klass = META_SCREEN_CAST_STREAM_SRC_GET_CLASS (src); - return klass->record_frame (src, data); + return klass->record_to_buffer (src, data, error); } static gboolean -meta_screen_cast_stream_src_blit_to_framebuffer (MetaScreenCastStreamSrc *src, - CoglFramebuffer *framebuffer) +meta_screen_cast_stream_src_record_to_framebuffer (MetaScreenCastStreamSrc *src, + CoglFramebuffer *framebuffer, + GError **error) +{ + MetaScreenCastStreamSrcClass *klass = + META_SCREEN_CAST_STREAM_SRC_GET_CLASS (src); + + return klass->record_to_framebuffer (src, framebuffer, error); +} + +static void +meta_screen_cast_stream_src_record_follow_up (MetaScreenCastStreamSrc *src) { MetaScreenCastStreamSrcClass *klass = META_SCREEN_CAST_STREAM_SRC_GET_CLASS (src); - return klass->blit_to_framebuffer (src, framebuffer); + klass->record_follow_up (src); } static void @@ -266,7 +286,7 @@ meta_screen_cast_stream_src_unset_cursor_metadata (MetaScreenCastStreamSrc *src, struct spa_meta_cursor *spa_meta_cursor) { - spa_meta_cursor->id = 1; + spa_meta_cursor->id = 0; } void @@ -407,9 +427,10 @@ } static gboolean -do_record_frame (MetaScreenCastStreamSrc *src, - struct spa_buffer *spa_buffer, - uint8_t *data) +do_record_frame (MetaScreenCastStreamSrc *src, + struct spa_buffer *spa_buffer, + uint8_t *data, + GError **error) { MetaScreenCastStreamSrcPrivate *priv = meta_screen_cast_stream_src_get_instance_private (src); @@ -417,7 +438,7 @@ if (spa_buffer->datas[0].data || spa_buffer->datas[0].type == SPA_DATA_MemFd) { - return meta_screen_cast_stream_src_record_frame (src, data); + return meta_screen_cast_stream_src_record_to_buffer (src, data, error); } else if (spa_buffer->datas[0].type == SPA_DATA_DmaBuf) { @@ -427,14 +448,56 @@ CoglFramebuffer *dmabuf_fbo = cogl_dma_buf_handle_get_framebuffer (dmabuf_handle); - return meta_screen_cast_stream_src_blit_to_framebuffer (src, dmabuf_fbo); + return meta_screen_cast_stream_src_record_to_framebuffer (src, + dmabuf_fbo, + error); } + g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, + "Unknown SPA buffer type %u", spa_buffer->datas[0].type); return FALSE; } +gboolean +meta_screen_cast_stream_src_pending_follow_up_frame (MetaScreenCastStreamSrc *src) +{ + MetaScreenCastStreamSrcPrivate *priv = + meta_screen_cast_stream_src_get_instance_private (src); + + return priv->follow_up_frame_source_id != 0; +} + +static gboolean +follow_up_frame_cb (gpointer user_data) +{ + MetaScreenCastStreamSrc *src = user_data; + MetaScreenCastStreamSrcPrivate *priv = + meta_screen_cast_stream_src_get_instance_private (src); + + priv->follow_up_frame_source_id = 0; + meta_screen_cast_stream_src_record_follow_up (src); + + return G_SOURCE_REMOVE; +} + +static void +maybe_schedule_follow_up_frame (MetaScreenCastStreamSrc *src, + int64_t timeout_us) +{ + MetaScreenCastStreamSrcPrivate *priv = + meta_screen_cast_stream_src_get_instance_private (src); + + if (priv->follow_up_frame_source_id) + return; + + priv->follow_up_frame_source_id = g_timeout_add (us2ms (timeout_us), + follow_up_frame_cb, + src); +} + void -meta_screen_cast_stream_src_maybe_record_frame (MetaScreenCastStreamSrc *src) +meta_screen_cast_stream_src_maybe_record_frame (MetaScreenCastStreamSrc *src, + MetaScreenCastRecordFlag flags) { MetaScreenCastStreamSrcPrivate *priv = meta_screen_cast_stream_src_get_instance_private (src); @@ -443,13 +506,29 @@ struct spa_buffer *spa_buffer; uint8_t *data = NULL; uint64_t now_us; + g_autoptr (GError) error = NULL; now_us = g_get_monotonic_time (); - if (priv->last_frame_timestamp_us != 0 && - (now_us - priv->last_frame_timestamp_us < - ((1000000 * priv->video_format.max_framerate.denom) / - priv->video_format.max_framerate.num))) - return; + if (priv->video_format.max_framerate.num > 0 && + priv->last_frame_timestamp_us != 0) + { + int64_t min_interval_us; + int64_t time_since_last_frame_us; + + min_interval_us = + ((G_USEC_PER_SEC * priv->video_format.max_framerate.denom) / + priv->video_format.max_framerate.num); + + time_since_last_frame_us = now_us - priv->last_frame_timestamp_us; + if (time_since_last_frame_us < min_interval_us) + { + int64_t timeout_us; + + timeout_us = min_interval_us - time_since_last_frame_us; + maybe_schedule_follow_up_frame (src, timeout_us); + return; + } + } if (!priv->pipewire_stream) return; @@ -467,34 +546,43 @@ return; } - if (do_record_frame (src, spa_buffer, data)) + if (!(flags & META_SCREEN_CAST_RECORD_FLAG_CURSOR_ONLY)) { - struct spa_meta_region *spa_meta_video_crop; + g_clear_handle_id (&priv->follow_up_frame_source_id, g_source_remove); + if (do_record_frame (src, spa_buffer, data, &error)) + { + struct spa_meta_region *spa_meta_video_crop; - spa_buffer->datas[0].chunk->size = spa_buffer->datas[0].maxsize; - spa_buffer->datas[0].chunk->stride = priv->video_stride; + spa_buffer->datas[0].chunk->size = spa_buffer->datas[0].maxsize; + spa_buffer->datas[0].chunk->stride = priv->video_stride; - /* Update VideoCrop if needed */ - spa_meta_video_crop = - spa_buffer_find_meta_data (spa_buffer, SPA_META_VideoCrop, - sizeof (*spa_meta_video_crop)); - if (spa_meta_video_crop) - { - if (meta_screen_cast_stream_src_get_videocrop (src, &crop_rect)) + /* Update VideoCrop if needed */ + spa_meta_video_crop = + spa_buffer_find_meta_data (spa_buffer, SPA_META_VideoCrop, + sizeof (*spa_meta_video_crop)); + if (spa_meta_video_crop) { - spa_meta_video_crop->region.position.x = crop_rect.x; - spa_meta_video_crop->region.position.y = crop_rect.y; - spa_meta_video_crop->region.size.width = crop_rect.width; - spa_meta_video_crop->region.size.height = crop_rect.height; - } - else - { - spa_meta_video_crop->region.position.x = 0; - spa_meta_video_crop->region.position.y = 0; - spa_meta_video_crop->region.size.width = priv->stream_width; - spa_meta_video_crop->region.size.height = priv->stream_height; + if (meta_screen_cast_stream_src_get_videocrop (src, &crop_rect)) + { + spa_meta_video_crop->region.position.x = crop_rect.x; + spa_meta_video_crop->region.position.y = crop_rect.y; + spa_meta_video_crop->region.size.width = crop_rect.width; + spa_meta_video_crop->region.size.height = crop_rect.height; + } + else + { + spa_meta_video_crop->region.position.x = 0; + spa_meta_video_crop->region.position.y = 0; + spa_meta_video_crop->region.size.width = priv->stream_width; + spa_meta_video_crop->region.size.height = priv->stream_height; + } } } + else + { + g_warning ("Failed to record screen cast frame: %s", error->message); + spa_buffer->datas[0].chunk->size = 0; + } } else { @@ -536,13 +624,9 @@ META_SCREEN_CAST_STREAM_SRC_GET_CLASS (src)->disable (src); - priv->is_enabled = FALSE; -} + g_clear_handle_id (&priv->follow_up_frame_source_id, g_source_remove); -static void -meta_screen_cast_stream_src_notify_closed (MetaScreenCastStreamSrc *src) -{ - g_signal_emit (src, signals[CLOSED], 0); + priv->is_enabled = FALSE; } static void @@ -559,7 +643,9 @@ { case PW_STREAM_STATE_ERROR: g_warning ("pipewire stream error: %s", error_message); - meta_screen_cast_stream_src_notify_closed (src); + if (meta_screen_cast_stream_src_is_enabled (src)) + meta_screen_cast_stream_src_disable (src); + priv->emit_closed_after_dispatch = TRUE; break; case PW_STREAM_STATE_PAUSED: if (priv->node_id == SPA_ID_INVALID && priv->pipewire_stream) @@ -827,11 +913,17 @@ const char *message) { MetaScreenCastStreamSrc *src = data; + MetaScreenCastStreamSrcPrivate *priv = + meta_screen_cast_stream_src_get_instance_private (src); g_warning ("pipewire remote error: id:%u %s", id, message); if (id == PW_ID_CORE && res == -EPIPE) - meta_screen_cast_stream_src_notify_closed (src); + { + if (meta_screen_cast_stream_src_is_enabled (src)) + meta_screen_cast_stream_src_disable (src); + priv->emit_closed_after_dispatch = TRUE; + } } static gboolean @@ -848,12 +940,18 @@ gpointer user_data) { MetaPipeWireSource *pipewire_source = (MetaPipeWireSource *) source; + MetaScreenCastStreamSrc *src = pipewire_source->src; + MetaScreenCastStreamSrcPrivate *priv = + meta_screen_cast_stream_src_get_instance_private (src); int result; result = pw_loop_iterate (pipewire_source->pipewire_loop, 0); if (result < 0) g_warning ("pipewire_loop_iterate failed: %s", spa_strerror (result)); + if (priv->emit_closed_after_dispatch) + g_signal_emit (src, signals[CLOSED], 0); + return TRUE; } @@ -875,13 +973,14 @@ }; static MetaPipeWireSource * -create_pipewire_source (void) +create_pipewire_source (MetaScreenCastStreamSrc *src) { MetaPipeWireSource *pipewire_source; pipewire_source = (MetaPipeWireSource *) g_source_new (&pipewire_source_funcs, sizeof (MetaPipeWireSource)); + pipewire_source->src = src; pipewire_source->pipewire_loop = pw_loop_new (NULL); if (!pipewire_source->pipewire_loop) { @@ -913,7 +1012,7 @@ MetaScreenCastStreamSrcPrivate *priv = meta_screen_cast_stream_src_get_instance_private (src); - priv->pipewire_source = create_pipewire_source (); + priv->pipewire_source = create_pipewire_source (src); if (!priv->pipewire_source) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, @@ -975,8 +1074,8 @@ if (meta_screen_cast_stream_src_is_enabled (src)) meta_screen_cast_stream_src_disable (src); - g_clear_pointer (&priv->dmabuf_handles, g_hash_table_destroy); g_clear_pointer (&priv->pipewire_stream, pw_stream_destroy); + g_clear_pointer (&priv->dmabuf_handles, g_hash_table_destroy); g_clear_pointer (&priv->pipewire_core, pw_core_disconnect); g_clear_pointer (&priv->pipewire_context, pw_context_destroy); g_source_destroy (&priv->pipewire_source->base); diff -Nru mutter-3.36.1/src/backends/meta-screen-cast-stream-src.h mutter-3.36.9/src/backends/meta-screen-cast-stream-src.h --- mutter-3.36.1/src/backends/meta-screen-cast-stream-src.h 2020-03-30 19:29:39.271885900 +0000 +++ mutter-3.36.9/src/backends/meta-screen-cast-stream-src.h 2021-03-15 23:07:33.265501000 +0000 @@ -37,6 +37,12 @@ typedef struct _MetaScreenCastStream MetaScreenCastStream; +typedef enum _MetaScreenCastRecordFlag +{ + META_SCREEN_CAST_RECORD_FLAG_NONE = 0, + META_SCREEN_CAST_RECORD_FLAG_CURSOR_ONLY = 1 << 0, +} MetaScreenCastRecordFlag; + #define META_TYPE_SCREEN_CAST_STREAM_SRC (meta_screen_cast_stream_src_get_type ()) G_DECLARE_DERIVABLE_TYPE (MetaScreenCastStreamSrc, meta_screen_cast_stream_src, @@ -53,17 +59,24 @@ float *frame_rate); void (* enable) (MetaScreenCastStreamSrc *src); void (* disable) (MetaScreenCastStreamSrc *src); - gboolean (* record_frame) (MetaScreenCastStreamSrc *src, - uint8_t *data); - gboolean (* blit_to_framebuffer) (MetaScreenCastStreamSrc *src, - CoglFramebuffer *framebuffer); + gboolean (* record_to_buffer) (MetaScreenCastStreamSrc *src, + uint8_t *data, + GError **error); + gboolean (* record_to_framebuffer) (MetaScreenCastStreamSrc *src, + CoglFramebuffer *framebuffer, + GError **error); + void (* record_follow_up) (MetaScreenCastStreamSrc *src); + gboolean (* get_videocrop) (MetaScreenCastStreamSrc *src, MetaRectangle *crop_rect); void (* set_cursor_metadata) (MetaScreenCastStreamSrc *src, struct spa_meta_cursor *spa_meta_cursor); }; -void meta_screen_cast_stream_src_maybe_record_frame (MetaScreenCastStreamSrc *src); +void meta_screen_cast_stream_src_maybe_record_frame (MetaScreenCastStreamSrc *src, + MetaScreenCastRecordFlag flags); + +gboolean meta_screen_cast_stream_src_pending_follow_up_frame (MetaScreenCastStreamSrc *src); MetaScreenCastStream * meta_screen_cast_stream_src_get_stream (MetaScreenCastStreamSrc *src); diff -Nru mutter-3.36.1/src/backends/meta-screen-cast-window-stream-src.c mutter-3.36.9/src/backends/meta-screen-cast-window-stream-src.c --- mutter-3.36.1/src/backends/meta-screen-cast-window-stream-src.c 2020-03-30 19:29:39.272885800 +0000 +++ mutter-3.36.9/src/backends/meta-screen-cast-window-stream-src.c 2021-03-15 23:07:33.265501000 +0000 @@ -327,8 +327,10 @@ MetaScreenCastWindowStreamSrc *window_src) { MetaScreenCastStreamSrc *src = META_SCREEN_CAST_STREAM_SRC (window_src); + MetaScreenCastRecordFlag flags; - meta_screen_cast_stream_src_maybe_record_frame (src); + flags = META_SCREEN_CAST_RECORD_FLAG_CURSOR_ONLY; + meta_screen_cast_stream_src_maybe_record_frame (src, flags); } static void @@ -339,40 +341,17 @@ window_src->screen_cast_window = NULL; } -static gboolean -is_cursor_in_stream (MetaScreenCastWindowStreamSrc *window_src) -{ - MetaBackend *backend = get_backend (window_src); - MetaCursorRenderer *cursor_renderer = - meta_backend_get_cursor_renderer (backend); - MetaCursorSprite *cursor_sprite; - graphene_point_t cursor_position; - MetaScreenCastWindow *screen_cast_window; - - cursor_sprite = meta_cursor_renderer_get_cursor (cursor_renderer); - - cursor_position = meta_cursor_renderer_get_position (cursor_renderer); - - screen_cast_window = window_src->screen_cast_window; - return meta_screen_cast_window_transform_cursor_position (screen_cast_window, - cursor_sprite, - &cursor_position, - NULL, - NULL); -} - static void sync_cursor_state (MetaScreenCastWindowStreamSrc *window_src) { MetaScreenCastStreamSrc *src = META_SCREEN_CAST_STREAM_SRC (window_src); - - if (!is_cursor_in_stream (window_src)) - return; + MetaScreenCastRecordFlag flags; if (meta_screen_cast_window_has_damage (window_src->screen_cast_window)) return; - meta_screen_cast_stream_src_maybe_record_frame (src); + flags = META_SCREEN_CAST_RECORD_FLAG_CURSOR_ONLY; + meta_screen_cast_stream_src_maybe_record_frame (src, flags); } static void @@ -401,6 +380,7 @@ MetaCursorTracker *cursor_tracker = meta_backend_get_cursor_tracker (backend); MetaWindowActor *window_actor; MetaScreenCastStream *stream; + MetaScreenCastRecordFlag flags; window_actor = meta_window_actor_from_window (get_window (window_src)); if (!window_actor) @@ -438,7 +418,8 @@ break; } - meta_screen_cast_stream_src_maybe_record_frame (src); + flags = META_SCREEN_CAST_RECORD_FLAG_NONE; + meta_screen_cast_stream_src_maybe_record_frame (src, flags); } static void @@ -451,8 +432,9 @@ } static gboolean -meta_screen_cast_window_stream_src_record_frame (MetaScreenCastStreamSrc *src, - uint8_t *data) +meta_screen_cast_window_stream_src_record_to_buffer (MetaScreenCastStreamSrc *src, + uint8_t *data, + GError **error) { MetaScreenCastWindowStreamSrc *window_src = META_SCREEN_CAST_WINDOW_STREAM_SRC (src); @@ -463,8 +445,9 @@ } static gboolean -meta_screen_cast_window_stream_src_blit_to_framebuffer (MetaScreenCastStreamSrc *src, - CoglFramebuffer *framebuffer) +meta_screen_cast_window_stream_src_record_to_framebuffer (MetaScreenCastStreamSrc *src, + CoglFramebuffer *framebuffer, + GError **error) { MetaScreenCastWindowStreamSrc *window_src = META_SCREEN_CAST_WINDOW_STREAM_SRC (src); @@ -477,9 +460,13 @@ stream_rect.height = get_stream_height (window_src); if (!meta_screen_cast_window_blit_to_framebuffer (window_src->screen_cast_window, - &stream_rect, - framebuffer)) - return FALSE; + &stream_rect, + framebuffer)) + { + g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, + "Failed to blit window content to framebuffer"); + return FALSE; + } stream = meta_screen_cast_stream_src_get_stream (src); switch (meta_screen_cast_stream_get_cursor_mode (stream)) @@ -498,6 +485,15 @@ } static void +meta_screen_cast_window_stream_record_follow_up (MetaScreenCastStreamSrc *src) +{ + MetaScreenCastRecordFlag flags; + + flags = META_SCREEN_CAST_RECORD_FLAG_NONE; + meta_screen_cast_stream_src_maybe_record_frame (src, flags); +} + +static void meta_screen_cast_window_stream_src_set_cursor_metadata (MetaScreenCastStreamSrc *src, struct spa_meta_cursor *spa_meta_cursor) { @@ -580,9 +576,12 @@ src_class->get_specs = meta_screen_cast_window_stream_src_get_specs; src_class->enable = meta_screen_cast_window_stream_src_enable; src_class->disable = meta_screen_cast_window_stream_src_disable; - src_class->record_frame = meta_screen_cast_window_stream_src_record_frame; - src_class->blit_to_framebuffer = - meta_screen_cast_window_stream_src_blit_to_framebuffer; + src_class->record_to_buffer = + meta_screen_cast_window_stream_src_record_to_buffer; + src_class->record_to_framebuffer = + meta_screen_cast_window_stream_src_record_to_framebuffer; + src_class->record_follow_up = + meta_screen_cast_window_stream_record_follow_up; src_class->get_videocrop = meta_screen_cast_window_stream_src_get_videocrop; src_class->set_cursor_metadata = meta_screen_cast_window_stream_src_set_cursor_metadata; } diff -Nru mutter-3.36.1/src/backends/meta-stage.c mutter-3.36.9/src/backends/meta-stage.c --- mutter-3.36.1/src/backends/meta-stage.c 2020-03-30 19:29:39.272885800 +0000 +++ mutter-3.36.9/src/backends/meta-stage.c 2021-03-15 23:07:33.266501000 +0000 @@ -65,7 +65,6 @@ ClutterStage parent; GPtrArray *watchers[N_WATCH_MODES]; - ClutterStageView *current_view; GList *overlays; gboolean is_active; @@ -169,6 +168,7 @@ static void notify_watchers_for_mode (MetaStage *stage, ClutterStageView *view, + ClutterPaintContext *paint_context, MetaStageWatchPhase watch_phase) { GPtrArray *watchers; @@ -183,7 +183,7 @@ if (watch->view && view != watch->view) continue; - watch->callback (stage, view, watch->user_data); + watch->callback (stage, view, paint_context, watch->user_data); } } @@ -192,20 +192,34 @@ ClutterPaintContext *paint_context) { MetaStage *stage = META_STAGE (actor); + ClutterStageView *view; GList *l; CLUTTER_ACTOR_CLASS (meta_stage_parent_class)->paint (actor, paint_context); - notify_watchers_for_mode (stage, stage->current_view, - META_STAGE_WATCH_AFTER_ACTOR_PAINT); + view = clutter_paint_context_get_stage_view (paint_context); + if (view) + { + notify_watchers_for_mode (stage, view, paint_context, + META_STAGE_WATCH_AFTER_ACTOR_PAINT); + } - g_signal_emit (stage, signals[ACTORS_PAINTED], 0); + if (!(clutter_paint_context_get_paint_flags (paint_context) & + CLUTTER_PAINT_FLAG_NO_PAINT_SIGNAL)) + g_signal_emit (stage, signals[ACTORS_PAINTED], 0); - for (l = stage->overlays; l; l = l->next) - meta_overlay_paint (l->data, paint_context); + if (!(clutter_paint_context_get_paint_flags (paint_context) & + CLUTTER_PAINT_FLAG_NO_CURSORS)) + { + for (l = stage->overlays; l; l = l->next) + meta_overlay_paint (l->data, paint_context); + } - notify_watchers_for_mode (stage, stage->current_view, - META_STAGE_WATCH_AFTER_OVERLAY_PAINT); + if (view) + { + notify_watchers_for_mode (stage, view, paint_context, + META_STAGE_WATCH_AFTER_OVERLAY_PAINT); + } } static void @@ -215,13 +229,14 @@ { MetaStage *meta_stage = META_STAGE (stage); - notify_watchers_for_mode (meta_stage, view, META_STAGE_WATCH_BEFORE_PAINT); + notify_watchers_for_mode (meta_stage, view, NULL, + META_STAGE_WATCH_BEFORE_PAINT); - meta_stage->current_view = view; CLUTTER_STAGE_CLASS (meta_stage_parent_class)->paint_view (stage, view, redraw_clip); - notify_watchers_for_mode (meta_stage, view, META_STAGE_WATCH_AFTER_PAINT); + notify_watchers_for_mode (meta_stage, view, NULL, + META_STAGE_WATCH_AFTER_PAINT); } static void @@ -380,7 +395,7 @@ meta_stage_set_active (MetaStage *stage, gboolean is_active) { - ClutterEvent event = { 0 }; + ClutterEvent *event; /* Used by the native backend to inform accessibility technologies * about when the stage loses and gains input focus. @@ -392,12 +407,12 @@ if (stage->is_active == is_active) return; - event.type = CLUTTER_STAGE_STATE; - clutter_event_set_stage (&event, CLUTTER_STAGE (stage)); - event.stage_state.changed_mask = CLUTTER_STAGE_STATE_ACTIVATED; + event = clutter_event_new (CLUTTER_STAGE_STATE); + clutter_event_set_stage (event, CLUTTER_STAGE (stage)); + event->stage_state.changed_mask = CLUTTER_STAGE_STATE_ACTIVATED; if (is_active) - event.stage_state.new_state = CLUTTER_STAGE_STATE_ACTIVATED; + event->stage_state.new_state = CLUTTER_STAGE_STATE_ACTIVATED; /* Emitting this StageState event will result in the stage getting * activated or deactivated (with the activated or deactivated signal @@ -412,7 +427,8 @@ * * See http://bugzilla.gnome.org/746670 */ - clutter_stage_event (CLUTTER_STAGE (stage), &event); + clutter_stage_event (CLUTTER_STAGE (stage), event); + clutter_event_free (event); } MetaStageWatch * diff -Nru mutter-3.36.1/src/backends/meta-stage-private.h mutter-3.36.9/src/backends/meta-stage-private.h --- mutter-3.36.1/src/backends/meta-stage-private.h 2020-03-30 19:29:39.272885800 +0000 +++ mutter-3.36.9/src/backends/meta-stage-private.h 2021-03-15 23:07:33.266501000 +0000 @@ -38,9 +38,10 @@ META_STAGE_WATCH_AFTER_PAINT, } MetaStageWatchPhase; -typedef void (* MetaStageWatchFunc) (MetaStage *stage, - ClutterStageView *view, - gpointer user_data); +typedef void (* MetaStageWatchFunc) (MetaStage *stage, + ClutterStageView *view, + ClutterPaintContext *paint_context, + gpointer user_data); ClutterActor *meta_stage_new (MetaBackend *backend); diff -Nru mutter-3.36.1/src/backends/native/meta-backend-native.c mutter-3.36.9/src/backends/native/meta-backend-native.c --- mutter-3.36.1/src/backends/native/meta-backend-native.c 2020-03-30 19:29:39.273885700 +0000 +++ mutter-3.36.9/src/backends/native/meta-backend-native.c 2021-03-15 23:07:33.267500900 +0000 @@ -366,6 +366,10 @@ if (retval != 0) g_warning ("Failed to set RT scheduler: %m"); } + +#ifdef HAVE_WAYLAND + meta_backend_init_wayland (backend); +#endif } static MetaMonitorManager * @@ -647,6 +651,10 @@ if (!native->launcher) return FALSE; +#ifdef HAVE_WAYLAND + meta_backend_init_wayland_display (META_BACKEND (native)); +#endif + native->udev = meta_udev_new (native); native->barrier_manager = meta_barrier_manager_native_new (); diff -Nru mutter-3.36.1/src/backends/native/meta-cursor-renderer-native.c mutter-3.36.9/src/backends/native/meta-cursor-renderer-native.c --- mutter-3.36.1/src/backends/native/meta-cursor-renderer-native.c 2020-03-30 19:29:39.274885700 +0000 +++ mutter-3.36.9/src/backends/native/meta-cursor-renderer-native.c 2021-03-15 23:07:33.268500800 +0000 @@ -407,13 +407,14 @@ else scale = 1.0; + transform = meta_logical_monitor_get_transform (data->in_logical_monitor); + transform = meta_monitor_logical_to_crtc_transform (monitor, transform); + meta_monitor_calculate_crtc_pos (monitor, monitor_mode, monitor_crtc_mode->output, - META_MONITOR_TRANSFORM_NORMAL, + transform, &crtc_x, &crtc_y); - transform = meta_logical_monitor_get_transform (data->in_logical_monitor); - transform = meta_monitor_logical_to_crtc_transform (monitor, transform); if (meta_monitor_transform_is_rotated (transform)) { crtc_width = monitor_crtc_mode->crtc_mode->height; diff -Nru mutter-3.36.1/src/backends/native/meta-gpu-kms.c mutter-3.36.9/src/backends/native/meta-gpu-kms.c --- mutter-3.36.1/src/backends/native/meta-gpu-kms.c 2020-03-30 19:29:39.275885600 +0000 +++ mutter-3.36.9/src/backends/native/meta-gpu-kms.c 2021-03-15 23:07:33.269500700 +0000 @@ -232,14 +232,28 @@ uint64_t state, MetaKmsUpdate *kms_update) { + MetaGpu *gpu = META_GPU (gpu_kms); GList *l; - for (l = meta_gpu_get_outputs (META_GPU (gpu_kms)); l; l = l->next) + for (l = meta_gpu_get_outputs (gpu); l; l = l->next) { MetaOutput *output = l->data; meta_output_kms_set_power_save_mode (output, state, kms_update); } + + if (state != META_POWER_SAVE_ON) + { + /* Turn off CRTCs for DPMS */ + for (l = meta_gpu_get_crtcs (gpu); l; l = l->next) + { + MetaCrtc *crtc = META_CRTC (l->data); + + meta_kms_update_mode_set (kms_update, + meta_crtc_kms_get_kms_crtc (crtc), + NULL, NULL); + } + } } gboolean diff -Nru mutter-3.36.1/src/backends/native/meta-kms.c mutter-3.36.9/src/backends/native/meta-kms.c --- mutter-3.36.1/src/backends/native/meta-kms.c 2020-03-30 19:29:39.280885500 +0000 +++ mutter-3.36.9/src/backends/native/meta-kms.c 2021-03-15 23:07:33.272500800 +0000 @@ -1,5 +1,6 @@ /* * Copyright (C) 2018 Red Hat + * Copyright 2020 DisplayLink (UK) Ltd. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -383,6 +384,7 @@ simple_impl_source->kms = kms; g_source_set_callback (source, func, user_data, user_data_destroy); + g_source_set_ready_time (source, 0); g_source_attach (source, g_main_context_get_thread_default ()); return source; diff -Nru mutter-3.36.1/src/backends/native/meta-kms-crtc.c mutter-3.36.9/src/backends/native/meta-kms-crtc.c --- mutter-3.36.1/src/backends/native/meta-kms-crtc.c 2020-03-30 19:29:39.277885700 +0000 +++ mutter-3.36.9/src/backends/native/meta-kms-crtc.c 2021-03-15 23:07:33.271500800 +0000 @@ -156,13 +156,10 @@ 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) { @@ -190,8 +187,6 @@ crtc->current_state.drm_mode = (drmModeModeInfo) { 0 }; } - is_gamma_valid = FALSE; - break; } @@ -212,35 +207,8 @@ 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 * @@ -255,6 +223,8 @@ crtc->id = drm_crtc->crtc_id; crtc->idx = idx; + meta_kms_crtc_read_state (crtc, impl_device, drm_crtc); + return crtc; } diff -Nru mutter-3.36.1/src/backends/native/meta-kms-impl-simple.c mutter-3.36.9/src/backends/native/meta-kms-impl-simple.c --- mutter-3.36.1/src/backends/native/meta-kms-impl-simple.c 2020-03-30 19:29:39.278885600 +0000 +++ mutter-3.36.9/src/backends/native/meta-kms-impl-simple.c 2021-03-15 23:07:33.271500800 +0000 @@ -1,6 +1,6 @@ /* * Copyright (C) 2018-2019 Red Hat - * Copyright (C) 2019 DisplayLink (UK) Ltd. + * Copyright (C) 2019-2020 DisplayLink (UK) Ltd. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -660,6 +660,9 @@ meta_kms_page_flip_data_ref (page_flip_data)); } + if (ret != 0) + meta_kms_page_flip_data_unref (page_flip_data); + if (ret == -EBUSY) { CachedModeSet *cached_mode_set; diff -Nru mutter-3.36.1/src/backends/native/meta-monitor-manager-kms.c mutter-3.36.9/src/backends/native/meta-monitor-manager-kms.c --- mutter-3.36.1/src/backends/native/meta-monitor-manager-kms.c 2020-03-30 19:29:39.281885600 +0000 +++ mutter-3.36.9/src/backends/native/meta-monitor-manager-kms.c 2021-03-15 23:07:33.273500700 +0000 @@ -303,6 +303,14 @@ if (!config) { + if (!manager->in_init) + { + MetaBackend *backend = meta_get_backend (); + MetaRenderer *renderer = meta_backend_get_renderer (backend); + + meta_renderer_native_reset_modes (META_RENDERER_NATIVE (renderer)); + } + manager->screen_width = META_MONITOR_MANAGER_MIN_SCREEN_WIDTH; manager->screen_height = META_MONITOR_MANAGER_MIN_SCREEN_HEIGHT; meta_monitor_manager_rebuild (manager, NULL); diff -Nru mutter-3.36.1/src/backends/native/meta-renderer-native.c mutter-3.36.9/src/backends/native/meta-renderer-native.c --- mutter-3.36.1/src/backends/native/meta-renderer-native.c 2020-03-30 19:29:39.282885600 +0000 +++ mutter-3.36.9/src/backends/native/meta-renderer-native.c 2021-03-15 23:07:33.275500500 +0000 @@ -2012,6 +2012,48 @@ } } +static MetaKmsUpdate * +unset_disabled_crtcs (MetaBackend *backend, + MetaKms *kms) +{ + MetaKmsUpdate *kms_update = NULL; + GList *l; + + for (l = meta_backend_get_gpus (backend); l; l = l->next) + { + MetaGpu *gpu = l->data; + GList *k; + + for (k = meta_gpu_get_crtcs (gpu); k; k = k->next) + { + MetaCrtc *crtc = k->data; + + if (crtc->config) + continue; + + kms_update = meta_kms_ensure_pending_update (kms); + meta_crtc_kms_set_mode (crtc, kms_update); + } + } + + return kms_update; +} + +static void +post_pending_update (MetaKms *kms) +{ + g_autoptr (MetaKmsFeedback) kms_feedback = NULL; + + kms_feedback = meta_kms_post_pending_update_sync (kms); + if (meta_kms_feedback_get_result (kms_feedback) != META_KMS_FEEDBACK_PASSED) + { + const GError *error = meta_kms_feedback_get_error (kms_feedback); + + if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_PERMISSION_DENIED)) + g_warning ("Failed to post KMS update: %s", error->message); + } +} + static void meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, const int *rectangles, @@ -2120,14 +2162,7 @@ COGL_TRACE_BEGIN (MetaRendererNativePostKmsUpdate, "Onscreen (post pending update)"); - kms_feedback = meta_kms_post_pending_update_sync (kms); - if (meta_kms_feedback_get_result (kms_feedback) != META_KMS_FEEDBACK_PASSED) - { - const GError *error = meta_kms_feedback_get_error (kms_feedback); - - if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_PERMISSION_DENIED)) - g_warning ("Failed to post KMS update: %s", error->message); - } + post_pending_update (kms); COGL_TRACE_END (MetaRendererNativePostKmsUpdate); } @@ -2146,6 +2181,7 @@ case META_RENDERER_NATIVE_MODE_GBM: { CoglFramebuffer *dmabuf_fb; + CoglDmaBufHandle *dmabuf_handle; struct gbm_bo *new_bo; int dmabuf_fd = -1; @@ -2182,8 +2218,11 @@ if (!dmabuf_fb) return NULL; - return cogl_dma_buf_handle_new (dmabuf_fb, dmabuf_fd, new_bo, - (GDestroyNotify) gbm_bo_destroy); + dmabuf_handle = + cogl_dma_buf_handle_new (dmabuf_fb, dmabuf_fd, new_bo, + (GDestroyNotify) gbm_bo_destroy); + cogl_object_unref (dmabuf_fb); + return dmabuf_handle; } break; #ifdef HAVE_EGL_DEVICE @@ -3037,6 +3076,7 @@ float scale; int onscreen_width; int onscreen_height; + MetaRectangle view_layout; MetaRendererView *view; GError *error = NULL; @@ -3108,8 +3148,11 @@ else scale = 1.0; + meta_rectangle_from_graphene_rect (&crtc->config->layout, + META_ROUNDING_STRATEGY_ROUND, + &view_layout); view = g_object_new (META_TYPE_RENDERER_VIEW, - "layout", &logical_monitor->rect, + "layout", &view_layout, "scale", scale, "framebuffer", onscreen, "offscreen", offscreen, @@ -3172,41 +3215,12 @@ if (renderer_native->pending_unset_disabled_crtcs) { - GList *l; - - for (l = meta_backend_get_gpus (backend); l; l = l->next) - { - MetaGpu *gpu = l->data; - GList *k; - - for (k = meta_gpu_get_crtcs (gpu); k; k = k->next) - { - MetaCrtc *crtc = k->data; - - if (crtc->config) - continue; - - kms_update = meta_kms_ensure_pending_update (kms); - meta_crtc_kms_set_mode (crtc, kms_update); - } - } - + kms_update = unset_disabled_crtcs (backend, kms); renderer_native->pending_unset_disabled_crtcs = FALSE; } if (kms_update) - { - g_autoptr (MetaKmsFeedback) kms_feedback = NULL; - - kms_feedback = meta_kms_post_pending_update_sync (kms); - if (meta_kms_feedback_get_result (kms_feedback) != META_KMS_FEEDBACK_PASSED) - { - const GError *error = meta_kms_feedback_get_error (kms_feedback); - - if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_PERMISSION_DENIED)) - g_warning ("Failed to post KMS update: %s", error->message); - } - } + post_pending_update (kms); } int64_t @@ -3788,6 +3802,21 @@ meta_kms_discard_pending_page_flips (kms); } +void +meta_renderer_native_reset_modes (MetaRendererNative *renderer_native) +{ + MetaRenderer *renderer = META_RENDERER (renderer_native); + MetaBackend *backend = meta_renderer_get_backend (renderer); + MetaBackendNative *backend_native = META_BACKEND_NATIVE (backend); + MetaKms *kms = meta_backend_native_get_kms (backend_native); + MetaKmsUpdate *kms_update; + + kms_update = unset_disabled_crtcs (backend, kms); + + if (kms_update) + post_pending_update (kms); +} + static MetaGpuKms * choose_primary_gpu_unchecked (MetaBackend *backend, MetaRendererNative *renderer_native) diff -Nru mutter-3.36.1/src/backends/native/meta-renderer-native.h mutter-3.36.9/src/backends/native/meta-renderer-native.h --- mutter-3.36.1/src/backends/native/meta-renderer-native.h 2020-03-30 19:29:39.282885600 +0000 +++ mutter-3.36.9/src/backends/native/meta-renderer-native.h 2021-03-15 23:07:33.275500500 +0000 @@ -55,4 +55,6 @@ int64_t meta_renderer_native_get_frame_counter (MetaRendererNative *renderer_native); +void meta_renderer_native_reset_modes (MetaRendererNative *renderer_native); + #endif /* META_RENDERER_NATIVE_H */ diff -Nru mutter-3.36.1/src/backends/native/meta-seat-native.c mutter-3.36.9/src/backends/native/meta-seat-native.c --- mutter-3.36.1/src/backends/native/meta-seat-native.c 2020-03-30 19:29:39.283885500 +0000 +++ mutter-3.36.9/src/backends/native/meta-seat-native.c 2021-03-15 23:07:33.276500700 +0000 @@ -424,6 +424,9 @@ meta_xkb_translate_state (event, seat->xkb, seat->button_state); event->motion.x = x; event->motion.y = y; + meta_input_device_native_translate_coordinates (input_device, stage, + &event->motion.x, + &event->motion.y); event->motion.axes = axes; clutter_event_set_device (event, seat->core_pointer); clutter_event_set_source_device (event, input_device); @@ -1377,35 +1380,6 @@ return FALSE; } -static gboolean -has_external_keyboard (MetaSeatNative *seat) -{ - GList *devices, *l; - gboolean has_external = FALSE; - - devices = g_udev_client_query_by_subsystem (seat->udev_client, "input"); - - for (l = devices; l; l = l->next) - { - if (!g_udev_device_has_property (l->data, "ID_INPUT_KEYBOARD")) - continue; - - /* May be "hid" or something else, we don't care. This property - * will not be present in virtual "AT Translated Set 2 keyboard" - * devices. - */ - if (!g_udev_device_has_property (l->data, "ID_TYPE")) - break; - - has_external = TRUE; - break; - } - - g_list_free_full (devices, g_object_unref); - - return has_external; -} - static void update_touch_mode (MetaSeatNative *seat) { @@ -1418,10 +1392,10 @@ else if (seat->has_tablet_switch && !seat->tablet_mode_switch_state) touch_mode = FALSE; /* If tablet mode is enabled, or if there is no tablet mode switch - * (eg. kiosk machines), check availability of external keyboards. + * (eg. kiosk machines), assume touch-mode. */ else - touch_mode = !seat->has_external_keyboard; + touch_mode = TRUE; if (seat->touch_mode != touch_mode) { @@ -1430,14 +1404,13 @@ } } -static void +static ClutterInputDevice * evdev_add_device (MetaSeatNative *seat, struct libinput_device *libinput_device) { ClutterInputDeviceType type; ClutterInputDevice *device, *master = NULL; ClutterActor *stage; - gboolean check_touch_mode = FALSE; device = meta_input_device_native_new (seat, libinput_device); stage = CLUTTER_ACTOR (meta_seat_native_get_stage (seat)); @@ -1460,30 +1433,7 @@ _clutter_input_device_add_slave (master, device); } - g_signal_emit_by_name (seat, "device-added", device); - - if (type == CLUTTER_KEYBOARD_DEVICE) - { - seat->has_external_keyboard = has_external_keyboard (seat); - check_touch_mode = TRUE; - } - else if (type == CLUTTER_TOUCHSCREEN_DEVICE) - { - seat->has_touchscreen = TRUE; - check_touch_mode = TRUE; - } - - if (libinput_device_has_capability (libinput_device, - LIBINPUT_DEVICE_CAP_SWITCH) && - libinput_device_switch_has_switch (libinput_device, - LIBINPUT_SWITCH_TABLET_MODE)) - { - seat->has_tablet_switch = TRUE; - check_touch_mode = TRUE; - } - - if (check_touch_mode) - update_touch_mode (seat); + return device; } static void @@ -1491,79 +1441,98 @@ MetaInputDeviceNative *device_evdev) { ClutterInputDevice *device; - ClutterInputDeviceType device_type; device = CLUTTER_INPUT_DEVICE (device_evdev); seat->devices = g_slist_remove (seat->devices, device); - g_signal_emit_by_name (seat, "device-removed", device); - - device_type = clutter_input_device_get_device_type (device); - - if (device_type == CLUTTER_KEYBOARD_DEVICE) - { - seat->has_external_keyboard = has_external_keyboard (seat); - update_touch_mode (seat); - } - else if (device_type == CLUTTER_TOUCHSCREEN_DEVICE) - { - seat->has_touchscreen = has_touchscreen (seat); - update_touch_mode (seat); - } - - if (seat->repeat_timer && seat->repeat_device == device) - meta_seat_native_clear_repeat_timer (seat); - - g_object_run_dispose (G_OBJECT (device)); g_object_unref (device); } -static void -flush_event_queue (void) +static gboolean +meta_seat_native_handle_device_event (ClutterSeat *seat, + ClutterEvent *event) { - ClutterEvent *event; + MetaSeatNative *seat_native = META_SEAT_NATIVE (seat); + ClutterInputDevice *device = event->device.device; + MetaInputDeviceNative *device_native = META_INPUT_DEVICE_NATIVE (device); + gboolean check_touch_mode; + + check_touch_mode = + clutter_input_device_get_device_type (device) == CLUTTER_TOUCHSCREEN_DEVICE; + + switch (event->type) + { + case CLUTTER_DEVICE_ADDED: + seat_native->has_touchscreen = check_touch_mode; + + if (libinput_device_has_capability (device_native->libinput_device, + LIBINPUT_DEVICE_CAP_SWITCH) && + libinput_device_switch_has_switch (device_native->libinput_device, + LIBINPUT_SWITCH_TABLET_MODE)) + { + seat_native->has_tablet_switch = TRUE; + check_touch_mode = TRUE; + } + break; - while ((event = clutter_event_get ()) != NULL) - { - _clutter_process_event (event); - clutter_event_free (event); + case CLUTTER_DEVICE_REMOVED: + if (check_touch_mode) + seat_native->has_touchscreen = has_touchscreen (seat_native); + + if (seat_native->repeat_timer && seat_native->repeat_device == device) + meta_seat_native_clear_repeat_timer (seat_native); + break; + + default: + break; } + + if (check_touch_mode) + update_touch_mode (seat_native); + + return TRUE; } static gboolean process_base_event (MetaSeatNative *seat, struct libinput_event *event) { - ClutterInputDevice *device; + ClutterInputDevice *device = NULL; + ClutterEvent *device_event; struct libinput_device *libinput_device; - gboolean handled = TRUE; switch (libinput_event_get_type (event)) { case LIBINPUT_EVENT_DEVICE_ADDED: libinput_device = libinput_event_get_device (event); - evdev_add_device (seat, libinput_device); + device = evdev_add_device (seat, libinput_device); + device_event = clutter_event_new (CLUTTER_DEVICE_ADDED); + clutter_event_set_device (device_event, device); break; case LIBINPUT_EVENT_DEVICE_REMOVED: - /* Flush all queued events, there - * might be some from this device. - */ - flush_event_queue (); - libinput_device = libinput_event_get_device (event); device = libinput_device_get_user_data (libinput_device); + device_event = clutter_event_new (CLUTTER_DEVICE_REMOVED); + clutter_event_set_device (device_event, device); evdev_remove_device (seat, META_INPUT_DEVICE_NATIVE (device)); break; default: - handled = FALSE; + device_event = NULL; } - return handled; + if (device_event) + { + device_event->device.stage = _clutter_input_device_get_stage (device); + queue_event (device_event); + return TRUE; + } + + return FALSE; } static ClutterScrollSource @@ -2530,8 +2499,6 @@ seat->udev_client = g_udev_client_new ((const gchar *[]) { "input", NULL }); - dispatch_libinput (seat); - source = meta_event_source_new (seat); seat->event_source = source; @@ -2550,7 +2517,6 @@ xkb_keymap_led_get_index (xkb_keymap, XKB_LED_NAME_SCROLL); } - seat->has_external_keyboard = has_external_keyboard (seat); seat->has_touchscreen = has_touchscreen (seat); update_touch_mode (seat); @@ -2818,6 +2784,7 @@ seat_class->get_supported_virtual_device_types = meta_seat_native_get_supported_virtual_device_types; seat_class->compress_motion = meta_seat_native_compress_motion; seat_class->warp_pointer = meta_seat_native_warp_pointer; + seat_class->handle_device_event = meta_seat_native_handle_device_event; props[PROP_SEAT_ID] = g_param_spec_string ("seat-id", diff -Nru mutter-3.36.1/src/backends/native/meta-seat-native.h mutter-3.36.9/src/backends/native/meta-seat-native.h --- mutter-3.36.1/src/backends/native/meta-seat-native.h 2020-03-30 19:29:39.283885500 +0000 +++ mutter-3.36.9/src/backends/native/meta-seat-native.h 2021-03-15 23:07:33.276500700 +0000 @@ -120,7 +120,6 @@ GUdevClient *udev_client; guint tablet_mode_switch_state : 1; - guint has_external_keyboard : 1; guint has_touchscreen : 1; guint has_tablet_switch : 1; guint touch_mode : 1; diff -Nru mutter-3.36.1/src/backends/x11/cm/meta-renderer-x11-cm.c mutter-3.36.9/src/backends/x11/cm/meta-renderer-x11-cm.c --- mutter-3.36.1/src/backends/x11/cm/meta-renderer-x11-cm.c 2020-03-30 19:29:39.285885300 +0000 +++ mutter-3.36.9/src/backends/x11/cm/meta-renderer-x11-cm.c 2021-03-15 23:07:33.277500600 +0000 @@ -24,14 +24,75 @@ #include "backends/x11/cm/meta-renderer-x11-cm.h" +#include "backends/meta-renderer-view.h" + struct _MetaRendererX11Cm { MetaRendererX11 parent; + + MetaRendererView *screen_view; }; G_DEFINE_TYPE (MetaRendererX11Cm, meta_renderer_x11_cm, META_TYPE_RENDERER_X11) +void +meta_renderer_x11_cm_ensure_screen_view (MetaRendererX11Cm *renderer_x11_cm, + int width, + int height) +{ + cairo_rectangle_int_t view_layout; + + if (renderer_x11_cm->screen_view) + return; + + view_layout = (cairo_rectangle_int_t) { + .width = width, + .height = height, + }; + renderer_x11_cm->screen_view = g_object_new (META_TYPE_RENDERER_VIEW, + "layout", &view_layout, + NULL); + meta_renderer_add_view (META_RENDERER (renderer_x11_cm), + renderer_x11_cm->screen_view); +} + +void +meta_renderer_x11_cm_resize (MetaRendererX11Cm *renderer_x11_cm, + int width, + int height) +{ + cairo_rectangle_int_t view_layout; + + view_layout = (cairo_rectangle_int_t) { + .width = width, + .height = height, + }; + + g_object_set (G_OBJECT (renderer_x11_cm->screen_view), + "layout", &view_layout, + NULL); +} + +void +meta_renderer_x11_cm_set_onscreen (MetaRendererX11Cm *renderer_x11_cm, + CoglOnscreen *onscreen) +{ + g_object_set (G_OBJECT (renderer_x11_cm->screen_view), + "framebuffer", onscreen, + NULL); +} + +static void +meta_renderer_x11_cm_rebuild_views (MetaRenderer *renderer) +{ + MetaRendererX11Cm *renderer_x11_cm = META_RENDERER_X11_CM (renderer); + + g_return_if_fail (!meta_renderer_get_views (renderer)); + + meta_renderer_add_view (renderer, renderer_x11_cm->screen_view); +} + static void meta_renderer_x11_cm_init (MetaRendererX11Cm *renderer_x11_cm) { @@ -40,4 +101,7 @@ static void meta_renderer_x11_cm_class_init (MetaRendererX11CmClass *klass) { + MetaRendererClass *renderer_class = META_RENDERER_CLASS (klass); + + renderer_class->rebuild_views = meta_renderer_x11_cm_rebuild_views; } diff -Nru mutter-3.36.1/src/backends/x11/cm/meta-renderer-x11-cm.h mutter-3.36.9/src/backends/x11/cm/meta-renderer-x11-cm.h --- mutter-3.36.1/src/backends/x11/cm/meta-renderer-x11-cm.h 2020-03-30 19:29:39.285885300 +0000 +++ mutter-3.36.9/src/backends/x11/cm/meta-renderer-x11-cm.h 2021-03-15 23:07:33.277500600 +0000 @@ -30,4 +30,15 @@ META, RENDERER_X11_CM, MetaRendererX11) +void meta_renderer_x11_cm_ensure_screen_view (MetaRendererX11Cm *renderer_x11_cm, + int width, + int height); + +void meta_renderer_x11_cm_resize (MetaRendererX11Cm *renderer_x11_cm, + int width, + int height); + +void meta_renderer_x11_cm_set_onscreen (MetaRendererX11Cm *renderer_x11_cm, + CoglOnscreen *onscreen); + #endif /* META_RENDERER_X11_CM_H */ diff -Nru mutter-3.36.1/src/backends/x11/meta-backend-x11.c mutter-3.36.9/src/backends/x11/meta-backend-x11.c --- mutter-3.36.1/src/backends/x11/meta-backend-x11.c 2020-03-30 19:29:39.285885300 +0000 +++ mutter-3.36.9/src/backends/x11/meta-backend-x11.c 2021-03-15 23:07:33.277500600 +0000 @@ -524,6 +524,8 @@ MetaBackendX11 *x11 = META_BACKEND_X11 (backend); MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11); MetaMonitorManager *monitor_manager; + ClutterBackend *clutter_backend; + ClutterSeat *seat; int major, minor; gboolean has_xi = FALSE; @@ -576,6 +578,11 @@ priv->touch_replay_sync_atom = XInternAtom (priv->xdisplay, "_MUTTER_TOUCH_SEQUENCE_SYNC", False); + + clutter_backend = meta_backend_get_clutter_backend (backend); + seat = clutter_backend_get_default_seat (clutter_backend); + meta_seat_x11_notify_devices (META_SEAT_X11 (seat), + CLUTTER_STAGE (meta_backend_get_stage (backend))); } static ClutterBackend * @@ -855,6 +862,7 @@ static void meta_backend_x11_init (MetaBackendX11 *x11) { + XInitThreads (); } Display * diff -Nru mutter-3.36.1/src/backends/x11/meta-input-device-x11.c mutter-3.36.9/src/backends/x11/meta-input-device-x11.c --- mutter-3.36.1/src/backends/x11/meta-input-device-x11.c 2020-03-30 19:29:39.287885400 +0000 +++ mutter-3.36.9/src/backends/x11/meta-input-device-x11.c 2021-03-15 23:07:33.279500500 +0000 @@ -38,7 +38,6 @@ float current_y; #ifdef HAVE_LIBWACOM - WacomDevice *wacom_device; GArray *group_modes; #endif }; @@ -93,13 +92,16 @@ ClutterInputDevice *other_device) { #ifdef HAVE_LIBWACOM - MetaInputDeviceX11 *device_x11 = META_INPUT_DEVICE_X11 (device); - MetaInputDeviceX11 *other_device_x11 = META_INPUT_DEVICE_X11 (other_device); + WacomDevice *wacom_device, *other_wacom_device; - if (device_x11->wacom_device && - other_device_x11->wacom_device && - libwacom_compare (device_x11->wacom_device, - other_device_x11->wacom_device, + wacom_device = + meta_input_device_get_wacom_device (META_INPUT_DEVICE (device)); + other_wacom_device = + meta_input_device_get_wacom_device (META_INPUT_DEVICE (other_device)); + + if (wacom_device && other_wacom_device && + libwacom_compare (wacom_device, + other_wacom_device, WCOMPARE_NORMAL) == 0) return TRUE; #endif @@ -122,9 +124,9 @@ static void meta_input_device_x11_finalize (GObject *object) { -#ifdef HAVE_LIBWACOM MetaInputDeviceX11 *device_xi2 = META_INPUT_DEVICE_X11 (object); +#ifdef HAVE_LIBWACOM if (device_xi2->group_modes) g_array_unref (device_xi2->group_modes); #endif @@ -413,9 +415,12 @@ { MetaInputDeviceX11 *device_x11 = META_INPUT_DEVICE_X11 (device); uint32_t n_buttons, n_modes, button_group, next_mode, i; + WacomDevice *wacom_device; GList *switch_buttons = NULL; - n_buttons = libwacom_get_num_buttons (device_x11->wacom_device); + wacom_device = + meta_input_device_get_wacom_device (META_INPUT_DEVICE (device)); + n_buttons = libwacom_get_num_buttons (wacom_device); for (i = 0; i < n_buttons; i++) { diff -Nru mutter-3.36.1/src/backends/x11/meta-monitor-manager-xrandr.c mutter-3.36.9/src/backends/x11/meta-monitor-manager-xrandr.c --- mutter-3.36.1/src/backends/x11/meta-monitor-manager-xrandr.c 2020-03-30 19:29:39.288885400 +0000 +++ mutter-3.36.9/src/backends/x11/meta-monitor-manager-xrandr.c 2021-03-15 23:07:33.280500400 +0000 @@ -453,6 +453,9 @@ meta_crtc_unset_config (crtc); } + if (!n_crtcs) + goto out; + g_assert (width > 0 && height > 0); /* The 'physical size' of an X screen is meaningless if that screen * can consist of many monitors. So just pick a size that make the @@ -549,6 +552,7 @@ output->is_primary = FALSE; } +out: XUngrabServer (manager_xrandr->xdisplay); XFlush (manager_xrandr->xdisplay); } @@ -595,6 +599,9 @@ if (!config) { + if (!manager->in_init) + apply_crtc_assignments (manager, TRUE, NULL, 0, NULL, 0); + meta_monitor_manager_xrandr_rebuild_derived (manager, NULL); return TRUE; } diff -Nru mutter-3.36.1/src/backends/x11/meta-seat-x11.c mutter-3.36.9/src/backends/x11/meta-seat-x11.c --- mutter-3.36.1/src/backends/x11/meta-seat-x11.c 2020-03-30 19:29:39.289885300 +0000 +++ mutter-3.36.9/src/backends/x11/meta-seat-x11.c 2021-03-15 23:07:33.281500600 +0000 @@ -38,7 +38,10 @@ PROP_OPCODE, PROP_POINTER_ID, PROP_KEYBOARD_ID, - N_PROPS + N_PROPS, + + /* This property is overridden */ + PROP_TOUCH_MODE, }; struct _MetaSeatX11 @@ -54,6 +57,8 @@ int pointer_id; int keyboard_id; int opcode; + guint has_touchscreens : 1; + guint touch_mode : 1; }; static GParamSpec *props[N_PROPS] = { 0 }; @@ -605,6 +610,20 @@ g_free (xi_event_mask.mask); } +static void +update_touch_mode (MetaSeatX11 *seat_x11) +{ + gboolean touch_mode; + + touch_mode = seat_x11->has_touchscreens; + + if (seat_x11->touch_mode == touch_mode) + return; + + seat_x11->touch_mode = touch_mode; + g_object_notify (G_OBJECT (seat_x11), "touch-mode"); +} + static ClutterInputDevice * add_device (MetaSeatX11 *seat_x11, ClutterBackend *backend, @@ -658,43 +677,72 @@ GINT_TO_POINTER (info->attachment)); _clutter_input_device_set_associated_device (device, master); _clutter_input_device_add_slave (master, device); - - g_signal_emit_by_name (seat_x11, "device-added", device); } } return device; } -static void -remove_device (MetaSeatX11 *seat_x11, - int device_id) +static gboolean +has_touchscreens (MetaSeatX11 *seat_x11) { - ClutterInputDevice *device; + GList *l; - device = g_hash_table_lookup (seat_x11->devices_by_id, - GINT_TO_POINTER (device_id)); + for (l = seat_x11->devices; l; l = l->next) + { + if (clutter_input_device_get_device_type (l->data) == CLUTTER_TOUCHSCREEN_DEVICE) + return TRUE; + } + + return FALSE; +} - if (device != NULL) +static void +remove_device (MetaSeatX11 *seat_x11, + ClutterInputDevice *device) +{ + if (seat_x11->core_pointer == device) { - if (seat_x11->core_pointer == device) - { - seat_x11->core_pointer = NULL; - } - else if (seat_x11->core_keyboard == device) - { - seat_x11->core_keyboard = NULL; - } - else - { - seat_x11->devices = g_list_remove (seat_x11->devices, device); - g_signal_emit_by_name (seat_x11, "device-removed", device); - } + seat_x11->core_pointer = NULL; + } + else if (seat_x11->core_keyboard == device) + { + seat_x11->core_keyboard = NULL; + } + else + { + seat_x11->devices = g_list_remove (seat_x11->devices, device); + } +} - g_object_run_dispose (G_OBJECT (device)); - g_hash_table_remove (seat_x11->devices_by_id, - GINT_TO_POINTER (device_id)); +static gboolean +meta_seat_x11_handle_device_event (ClutterSeat *seat, + ClutterEvent *event) +{ + MetaSeatX11 *seat_x11 = META_SEAT_X11 (seat); + ClutterInputDevice *device = event->device.device; + gboolean is_touch; + + is_touch = + clutter_input_device_get_device_type (device) == CLUTTER_TOUCHSCREEN_DEVICE; + + switch (event->type) + { + case CLUTTER_DEVICE_ADDED: + seat_x11->has_touchscreens |= is_touch; + break; + case CLUTTER_DEVICE_REMOVED: + if (is_touch) + seat_x11->has_touchscreens = has_touchscreens (seat_x11); + break; + default: + break; } + + if (is_touch) + update_touch_mode (seat_x11); + + return TRUE; } static void @@ -756,12 +804,14 @@ return serial_id; } -static void +static gboolean translate_hierarchy_event (ClutterBackend *backend, MetaSeatX11 *seat_x11, - XIHierarchyEvent *ev) + XIHierarchyEvent *ev, + ClutterEvent *event) { int i; + gboolean retval = FALSE; for (i = 0; i < ev->num_info; i++) { @@ -781,15 +831,38 @@ clutter_x11_untrap_x_errors (); if (info != NULL) { - add_device (seat_x11, backend, &info[0], FALSE); + ClutterInputDevice *device; + + device = add_device (seat_x11, backend, &info[0], FALSE); + + event->any.type = CLUTTER_DEVICE_ADDED; + event->any.time = ev->time; + clutter_event_set_device (event, device); + + retval = TRUE; XIFreeDeviceInfo (info); } } else if (ev->info[i].flags & XIDeviceDisabled) { + g_autoptr (ClutterInputDevice) device = NULL; g_debug ("Hierarchy event: device disabled"); - remove_device (seat_x11, ev->info[i].deviceid); + g_hash_table_steal_extended (seat_x11->devices_by_id, + GINT_TO_POINTER (ev->info[i].deviceid), + NULL, + (gpointer) &device); + + if (device != NULL) + { + remove_device (seat_x11, device); + + event->any.type = CLUTTER_DEVICE_REMOVED; + event->any.time = ev->time; + clutter_event_set_device (event, device); + + retval = TRUE; + } } else if ((ev->info[i].flags & XISlaveAttached) || (ev->info[i].flags & XISlaveDetached)) @@ -836,6 +909,8 @@ } } } + + return retval; } static void @@ -1068,6 +1143,9 @@ } break; + case XI_HierarchyChanged: + return CLUTTER_STAGE (meta_backend_get_stage (meta_get_backend ())); + default: break; } @@ -1272,6 +1350,7 @@ case PROP_KEYBOARD_ID: seat_x11->keyboard_id = g_value_get_int (value); break; + case PROP_TOUCH_MODE: default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } @@ -1296,11 +1375,33 @@ case PROP_KEYBOARD_ID: g_value_set_int (value, seat_x11->keyboard_id); break; + case PROP_TOUCH_MODE: + g_value_set_boolean (value, seat_x11->touch_mode); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } +void +meta_seat_x11_notify_devices (MetaSeatX11 *seat_x11, + ClutterStage *stage) +{ + GHashTableIter iter; + ClutterInputDevice *device; + + g_hash_table_iter_init (&iter, seat_x11->devices_by_id); + while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &device)) + { + ClutterEvent *event; + + event = clutter_event_new (CLUTTER_DEVICE_ADDED); + clutter_event_set_device (event, device); + clutter_event_set_stage (event, stage); + clutter_do_event (event); + } +} + static void meta_seat_x11_constructed (GObject *object) { @@ -1523,6 +1624,7 @@ seat_class->create_virtual_device = meta_seat_x11_create_virtual_device; seat_class->get_supported_virtual_device_types = meta_seat_x11_get_supported_virtual_device_types; seat_class->warp_pointer = meta_seat_x11_warp_pointer; + seat_class->handle_device_event = meta_seat_x11_handle_device_event; props[PROP_OPCODE] = g_param_spec_int ("opcode", @@ -1547,6 +1649,9 @@ G_PARAM_CONSTRUCT_ONLY); g_object_class_install_properties (object_class, N_PROPS, props); + + g_object_class_override_property (object_class, PROP_TOUCH_MODE, + "touch-mode"); } static void @@ -1622,8 +1727,7 @@ return FALSE; } - if (!(xi_event->evtype == XI_HierarchyChanged || - xi_event->evtype == XI_DeviceChanged || + if (!(xi_event->evtype == XI_DeviceChanged || xi_event->evtype == XI_PropertyEvent)) { stage = get_event_stage (seat, xi_event); @@ -1641,9 +1745,8 @@ { XIHierarchyEvent *xev = (XIHierarchyEvent *) xi_event; - translate_hierarchy_event (backend, seat, xev); + retval = translate_hierarchy_event (backend, seat, xev, event); } - retval = FALSE; break; case XI_DeviceChanged: @@ -1721,6 +1824,10 @@ GINT_TO_POINTER (xev->deviceid)); clutter_event_set_device (event, device); + if (clutter_input_device_get_device_mode (device) == CLUTTER_INPUT_MODE_MASTER && + stage != NULL) + _clutter_input_device_set_stage (device, stage); + /* XXX keep this in sync with the evdev device manager */ n = print_keysym (event->key.keyval, buffer, sizeof (buffer)); if (n == 0) diff -Nru mutter-3.36.1/src/backends/x11/meta-seat-x11.h mutter-3.36.9/src/backends/x11/meta-seat-x11.h --- mutter-3.36.1/src/backends/x11/meta-seat-x11.h 2020-03-30 19:29:39.289885300 +0000 +++ mutter-3.36.9/src/backends/x11/meta-seat-x11.h 2021-03-15 23:07:33.281500600 +0000 @@ -36,6 +36,8 @@ int device_id); void meta_seat_x11_select_stage_events (MetaSeatX11 *seat, ClutterStage *stage); +void meta_seat_x11_notify_devices (MetaSeatX11 *seat_x11, + ClutterStage *stage); G_END_DECLS diff -Nru mutter-3.36.1/src/backends/x11/meta-stage-x11.c mutter-3.36.9/src/backends/x11/meta-stage-x11.c --- mutter-3.36.1/src/backends/x11/meta-stage-x11.c 2020-03-30 19:29:39.289885300 +0000 +++ mutter-3.36.9/src/backends/x11/meta-stage-x11.c 2021-03-15 23:07:33.281500600 +0000 @@ -26,15 +26,17 @@ #include #endif +#include "backends/x11/cm/meta-backend-x11-cm.h" +#include "backends/x11/cm/meta-renderer-x11-cm.h" +#include "backends/x11/meta-backend-x11.h" +#include "backends/x11/meta-seat-x11.h" +#include "backends/x11/meta-stage-x11.h" #include "clutter/clutter-mutter.h" #include "clutter/x11/clutter-x11.h" #include "clutter/x11/clutter-backend-x11.h" #include "cogl/cogl.h" #include "core/display-private.h" #include "meta/meta-x11-errors.h" -#include "meta-backend-x11.h" -#include "meta-seat-x11.h" -#include "meta-stage-x11.h" #define STAGE_X11_IS_MAPPED(s) ((((MetaStageX11 *) (s))->wm_state & STAGE_X11_WITHDRAWN) == 0) @@ -287,8 +289,6 @@ clutter_stage_window_parent_iface->unrealize (stage_window); - g_list_free (stage_x11->legacy_views); - g_clear_object (&stage_x11->legacy_view); g_clear_pointer (&stage_x11->onscreen, cogl_object_unref); } @@ -330,10 +330,13 @@ stage_cogl, NULL); - if (stage_x11->legacy_view) - g_object_set (G_OBJECT (stage_x11->legacy_view), - "framebuffer", stage_x11->onscreen, - NULL); + if (META_IS_BACKEND_X11_CM (stage_x11->backend)) + { + MetaRenderer *renderer = meta_backend_get_renderer (stage_x11->backend); + MetaRendererX11Cm *renderer_x11_cm = META_RENDERER_X11_CM (renderer); + + meta_renderer_x11_cm_set_onscreen (renderer_x11_cm, stage_x11->onscreen); + } /* We just created a window of the size of the actor. No need to fix the size of the stage, just update it. */ @@ -522,34 +525,13 @@ return stage_x11->clipped_redraws_cool_off == 0; } -static void -ensure_legacy_view (ClutterStageWindow *stage_window) -{ - MetaStageX11 *stage_x11 = META_STAGE_X11 (stage_window); - cairo_rectangle_int_t view_layout; - CoglFramebuffer *framebuffer; - - if (stage_x11->legacy_view) - return; - - _clutter_stage_window_get_geometry (stage_window, &view_layout); - framebuffer = COGL_FRAMEBUFFER (stage_x11->onscreen); - stage_x11->legacy_view = g_object_new (CLUTTER_TYPE_STAGE_VIEW_COGL, - "layout", &view_layout, - "framebuffer", framebuffer, - NULL); - stage_x11->legacy_views = g_list_append (stage_x11->legacy_views, - stage_x11->legacy_view); -} - static GList * meta_stage_x11_get_views (ClutterStageWindow *stage_window) { MetaStageX11 *stage_x11 = META_STAGE_X11 (stage_window); + MetaRenderer *renderer = meta_backend_get_renderer (stage_x11->backend); - ensure_legacy_view (stage_window); - - return stage_x11->legacy_views; + return meta_renderer_get_views (renderer); } static int64_t @@ -581,6 +563,9 @@ static void meta_stage_x11_init (MetaStageX11 *stage) { + MetaRenderer *renderer; + MetaRendererX11Cm *renderer_x11_cm; + stage->xwin = None; stage->xwin_width = 640; stage->xwin_height = 480; @@ -591,6 +576,19 @@ stage->accept_focus = TRUE; stage->title = NULL; + + stage->backend = meta_get_backend (); + g_assert (stage->backend); + + if (META_IS_BACKEND_X11_CM (stage->backend)) + { + renderer = meta_backend_get_renderer (stage->backend); + renderer_x11_cm = META_RENDERER_X11_CM (renderer); + + meta_renderer_x11_cm_ensure_screen_view (renderer_x11_cm, + stage->xwin_width, + stage->xwin_height); + } } static void @@ -778,16 +776,16 @@ * X11 compositing manager, we need to reset the legacy * stage view, now that it has a new size. */ - if (stage_x11->legacy_view) + if (META_IS_BACKEND_X11_CM (stage_x11->backend)) { - cairo_rectangle_int_t view_layout = { - .width = stage_width, - .height = stage_height - }; - - g_object_set (G_OBJECT (stage_x11->legacy_view), - "layout", &view_layout, - NULL); + MetaBackend *backend = stage_x11->backend; + MetaRenderer *renderer = meta_backend_get_renderer (backend); + MetaRendererX11Cm *renderer_x11_cm = + META_RENDERER_X11_CM (renderer); + + meta_renderer_x11_cm_resize (renderer_x11_cm, + stage_width, + stage_height); } } } @@ -845,12 +843,16 @@ g_debug ("Client message for stage, win:0x%x", (unsigned int) xevent->xany.window); - if (handle_wm_protocols_event (backend_x11, stage_x11, xevent)) + if (xevent->xclient.message_type == backend_x11->atom_WM_PROTOCOLS) { - event->any.type = CLUTTER_DELETE; - event->any.stage = stage; - res = TRUE; + if (handle_wm_protocols_event (backend_x11, stage_x11, xevent)) + { + event->any.type = CLUTTER_DELETE; + event->any.stage = stage; + res = TRUE; + } } + break; default: diff -Nru mutter-3.36.1/src/backends/x11/meta-stage-x11.h mutter-3.36.9/src/backends/x11/meta-stage-x11.h --- mutter-3.36.1/src/backends/x11/meta-stage-x11.h 2020-03-30 19:29:39.289885300 +0000 +++ mutter-3.36.9/src/backends/x11/meta-stage-x11.h 2021-03-15 23:07:33.281500600 +0000 @@ -25,6 +25,7 @@ #include #include +#include "backends/meta-backend-private.h" #include "clutter/clutter-mutter.h" #include "clutter/x11/clutter-x11.h" @@ -51,14 +52,13 @@ { ClutterStageCogl parent_instance; + MetaBackend *backend; + CoglOnscreen *onscreen; Window xwin; gint xwin_width; gint xwin_height; /* FIXME target_width / height */ - ClutterStageView *legacy_view; - GList *legacy_views; - CoglFrameClosure *frame_closure; gchar *title; diff -Nru mutter-3.36.1/src/backends/x11/nested/meta-backend-x11-nested.c mutter-3.36.9/src/backends/x11/nested/meta-backend-x11-nested.c --- mutter-3.36.1/src/backends/x11/nested/meta-backend-x11-nested.c 2020-03-30 19:29:39.290885200 +0000 +++ mutter-3.36.9/src/backends/x11/nested/meta-backend-x11-nested.c 2021-03-15 23:07:33.282500500 +0000 @@ -33,8 +33,16 @@ MetaGpu *gpu; } MetaBackendX11NestedPrivate; -G_DEFINE_TYPE_WITH_PRIVATE (MetaBackendX11Nested, meta_backend_x11_nested, - META_TYPE_BACKEND_X11) +static GInitableIface *initable_parent_iface; + +static void +initable_iface_init (GInitableIface *initable_iface); + +G_DEFINE_TYPE_WITH_CODE (MetaBackendX11Nested, meta_backend_x11_nested, + META_TYPE_BACKEND_X11, + G_ADD_PRIVATE (MetaBackendX11Nested) + G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, + initable_iface_init)); static MetaRenderer * meta_backend_x11_nested_create_renderer (MetaBackend *backend, @@ -202,6 +210,39 @@ } static void +meta_backend_x11_nested_post_init (MetaBackend *backend) +{ + MetaBackendClass *backend_class = + META_BACKEND_CLASS (meta_backend_x11_nested_parent_class); + + backend_class->post_init (backend); + +#ifdef HAVE_WAYLAND + meta_backend_init_wayland (backend); +#endif +} + +static gboolean +meta_backend_x11_nested_initable_init (GInitable *initable, + GCancellable *cancellable, + GError **error) +{ +#ifdef HAVE_WAYLAND + meta_backend_init_wayland_display (META_BACKEND (initable)); +#endif + + return initable_parent_iface->init (initable, cancellable, error); +} + +static void +initable_iface_init (GInitableIface *initable_iface) +{ + initable_parent_iface = g_type_interface_peek_parent (initable_iface); + + initable_iface->init = meta_backend_x11_nested_initable_init; +} + +static void meta_backend_x11_nested_constructed (GObject *object) { MetaBackendX11Nested *backend_x11_nested = META_BACKEND_X11_NESTED (object); @@ -229,6 +270,7 @@ object_class->constructed = meta_backend_x11_nested_constructed; + backend_class->post_init = meta_backend_x11_nested_post_init; backend_class->create_renderer = meta_backend_x11_nested_create_renderer; backend_class->create_monitor_manager = meta_backend_x11_nested_create_monitor_manager; backend_class->create_cursor_renderer = meta_backend_x11_nested_create_cursor_renderer; diff -Nru mutter-3.36.1/src/backends/x11/nested/meta-renderer-x11-nested.c mutter-3.36.9/src/backends/x11/nested/meta-renderer-x11-nested.c --- mutter-3.36.1/src/backends/x11/nested/meta-renderer-x11-nested.c 2020-03-30 19:29:39.290885200 +0000 +++ mutter-3.36.9/src/backends/x11/nested/meta-renderer-x11-nested.c 2021-03-15 23:07:33.282500500 +0000 @@ -167,7 +167,8 @@ "framebuffer", COGL_FRAMEBUFFER (fake_onscreen), NULL); - meta_renderer_set_legacy_view (renderer, legacy_view); + g_assert (!meta_renderer_get_views (renderer)); + meta_renderer_add_view (renderer, legacy_view); } static MetaRendererView * diff -Nru mutter-3.36.1/src/compositor/compositor.c mutter-3.36.9/src/compositor/compositor.c --- mutter-3.36.1/src/compositor/compositor.c 2020-03-30 19:29:39.292885300 +0000 +++ mutter-3.36.9/src/compositor/compositor.c 2021-03-15 23:07:33.284500400 +0000 @@ -63,7 +63,6 @@ #include "clutter/clutter-mutter.h" #include "cogl/cogl.h" #include "compositor/meta-window-actor-x11.h" -#include "compositor/meta-window-actor-wayland.h" #include "compositor/meta-window-actor-private.h" #include "compositor/meta-window-group-private.h" #include "core/display-private.h" @@ -82,6 +81,7 @@ #include "x11/meta-x11-display-private.h" #ifdef HAVE_WAYLAND +#include "compositor/meta-window-actor-wayland.h" #include "wayland/meta-wayland-private.h" #endif @@ -108,11 +108,6 @@ gulong stage_presented_id; gulong stage_after_paint_id; - int64_t server_time_query_time; - int64_t server_time_offset; - - gboolean server_time_is_monotonic_time; - ClutterActor *stage; ClutterActor *window_group; @@ -490,11 +485,6 @@ for (l = priv->windows; l; l = l->next) meta_window_actor_post_paint (l->data); - -#ifdef HAVE_WAYLAND - if (meta_is_wayland_compositor ()) - meta_wayland_compositor_paint_finished (meta_wayland_compositor_get_default ()); -#endif } static void @@ -1128,6 +1118,11 @@ meta_compositor_get_instance_private (compositor); CoglGraphicsResetStatus status; +#ifdef HAVE_WAYLAND + if (meta_is_wayland_compositor ()) + meta_wayland_compositor_paint_finished (meta_wayland_compositor_get_default ()); +#endif + status = cogl_get_graphics_reset_status (priv->context); switch (status) { @@ -1426,7 +1421,7 @@ } /** - * meta_compositor_monotonic_time_to_server_time: + * meta_compositor_monotonic_to_high_res_xserver_time: * @display: a #MetaDisplay * @monotonic_time: time in the units of g_get_monotonic_time() * @@ -1439,40 +1434,13 @@ * a time representation with high accuracy. If there is not a common * time source, then the time synchronization will be less accurate. */ -gint64 -meta_compositor_monotonic_time_to_server_time (MetaDisplay *display, - gint64 monotonic_time) +int64_t +meta_compositor_monotonic_to_high_res_xserver_time (MetaCompositor *compositor, + int64_t monotonic_time_us) { - MetaCompositor *compositor = display->compositor; - MetaCompositorPrivate *priv = - meta_compositor_get_instance_private (compositor); + MetaCompositorClass *klass = META_COMPOSITOR_GET_CLASS (compositor); - if (priv->server_time_query_time == 0 || - (!priv->server_time_is_monotonic_time && - monotonic_time > priv->server_time_query_time + 10*1000*1000)) /* 10 seconds */ - { - guint32 server_time = meta_display_get_current_time_roundtrip (display); - gint64 server_time_usec = (gint64)server_time * 1000; - gint64 current_monotonic_time = g_get_monotonic_time (); - priv->server_time_query_time = current_monotonic_time; - - /* If the server time is within a second of the monotonic time, - * we assume that they are identical. This seems like a big margin, - * but we want to be as robust as possible even if the system - * is under load and our processing of the server response is - * delayed. - */ - if (server_time_usec > current_monotonic_time - 1000*1000 && - server_time_usec < current_monotonic_time + 1000*1000) - priv->server_time_is_monotonic_time = TRUE; - - priv->server_time_offset = server_time_usec - current_monotonic_time; - } - - if (priv->server_time_is_monotonic_time) - return monotonic_time; - else - return monotonic_time + priv->server_time_offset; + return klass->monotonic_to_high_res_xserver_time (compositor, monotonic_time_us); } void diff -Nru mutter-3.36.1/src/compositor/compositor-private.h mutter-3.36.9/src/compositor/compositor-private.h --- mutter-3.36.1/src/compositor/compositor-private.h 2020-03-30 19:29:39.291885400 +0000 +++ mutter-3.36.9/src/compositor/compositor-private.h 2021-03-15 23:07:33.283500400 +0000 @@ -24,6 +24,8 @@ void (* post_paint) (MetaCompositor *compositor); void (* remove_window) (MetaCompositor *compositor, MetaWindow *window); + int64_t (* monotonic_to_high_res_xserver_time) (MetaCompositor *compositor, + int64_t time_us); }; void meta_compositor_remove_window_actor (MetaCompositor *compositor, @@ -41,8 +43,8 @@ MetaPluginManager * meta_compositor_get_plugin_manager (MetaCompositor *compositor); -gint64 meta_compositor_monotonic_time_to_server_time (MetaDisplay *display, - gint64 monotonic_time); +int64_t meta_compositor_monotonic_to_high_res_xserver_time (MetaCompositor *compositor, + int64_t monotonic_time_us); void meta_compositor_flash_window (MetaCompositor *compositor, MetaWindow *window); @@ -67,4 +69,38 @@ gboolean meta_compositor_is_switching_workspace (MetaCompositor *compositor); +static inline int64_t +us (int64_t us) +{ + return us; +} + +static inline int64_t +ms2us (int64_t ms) +{ + return us (ms * 1000); +} + +static inline int64_t +s2us (int64_t s) +{ + return ms2us(s * 1000); +} + +/* + * This function takes a 64 bit time stamp from the monotonic clock, and clamps + * it to the scope of the X server clock, without losing the granularity. + */ +static inline int64_t +meta_translate_to_high_res_xserver_time (int64_t time_us) +{ + int64_t us; + int64_t ms; + + us = time_us % 1000; + ms = time_us / 1000; + + return ms2us (ms & 0xffffffff) + us; +} + #endif /* META_COMPOSITOR_PRIVATE_H */ diff -Nru mutter-3.36.1/src/compositor/meta-background-actor.c mutter-3.36.9/src/compositor/meta-background-actor.c --- mutter-3.36.1/src/compositor/meta-background-actor.c 2020-03-30 19:29:39.292885300 +0000 +++ mutter-3.36.9/src/compositor/meta-background-actor.c 2021-03-15 23:07:33.284500400 +0000 @@ -354,7 +354,7 @@ guint8 opacity; float color_component; CoglFramebuffer *fb; - CoglPipelineFilter filter; + CoglPipelineFilter min_filter, mag_filter; opacity = clutter_actor_get_paint_opacity (CLUTTER_ACTOR (self)); if (opacity < 255) @@ -455,11 +455,17 @@ actor_pixel_rect->width, actor_pixel_rect->height, NULL, NULL)) - filter = COGL_PIPELINE_FILTER_NEAREST; + { + min_filter = COGL_PIPELINE_FILTER_NEAREST; + mag_filter = COGL_PIPELINE_FILTER_NEAREST; + } else - filter = COGL_PIPELINE_FILTER_LINEAR; + { + min_filter = COGL_PIPELINE_FILTER_LINEAR_MIPMAP_NEAREST; + mag_filter = COGL_PIPELINE_FILTER_LINEAR; + } - cogl_pipeline_set_layer_filters (self->pipeline, 0, filter, filter); + cogl_pipeline_set_layer_filters (self->pipeline, 0, min_filter, mag_filter); } static void diff -Nru mutter-3.36.1/src/compositor/meta-background.c mutter-3.36.9/src/compositor/meta-background.c --- mutter-3.36.1/src/compositor/meta-background.c 2020-03-30 19:29:39.293885200 +0000 +++ mutter-3.36.9/src/compositor/meta-background.c 2021-03-15 23:07:33.284500400 +0000 @@ -747,6 +747,25 @@ } } +static int +get_best_mipmap_level (CoglTexture *texture, + int visible_width, + int visible_height) +{ + int mipmap_width = cogl_texture_get_width (texture); + int mipmap_height = cogl_texture_get_height (texture); + int halves = 0; + + while (mipmap_width >= visible_width && mipmap_height >= visible_height) + { + halves++; + mipmap_width /= 2; + mipmap_height /= 2; + } + + return MAX (0, halves - 1); +} + CoglTexture * meta_background_get_texture (MetaBackground *self, int monitor_index, @@ -854,10 +873,17 @@ if (texture2 != NULL && self->blend_factor != 0.0) { CoglPipeline *pipeline = create_pipeline (PIPELINE_REPLACE); + int mipmap_level; + + mipmap_level = get_best_mipmap_level (texture2, + texture_width, + texture_height); + cogl_pipeline_set_color4f (pipeline, self->blend_factor, self->blend_factor, self->blend_factor, self->blend_factor); cogl_pipeline_set_layer_texture (pipeline, 0, texture2); cogl_pipeline_set_layer_wrap_mode (pipeline, 0, get_wrap_mode (self->style)); + cogl_pipeline_set_layer_max_mipmap_level (pipeline, 0, mipmap_level); bare_region_visible = draw_texture (self, monitor->fbo, pipeline, @@ -876,6 +902,12 @@ if (texture1 != NULL && self->blend_factor != 1.0) { CoglPipeline *pipeline = create_pipeline (PIPELINE_ADD); + int mipmap_level; + + mipmap_level = get_best_mipmap_level (texture1, + texture_width, + texture_height); + cogl_pipeline_set_color4f (pipeline, (1 - self->blend_factor), (1 - self->blend_factor), @@ -883,6 +915,7 @@ (1 - self->blend_factor));; cogl_pipeline_set_layer_texture (pipeline, 0, texture1); cogl_pipeline_set_layer_wrap_mode (pipeline, 0, get_wrap_mode (self->style)); + cogl_pipeline_set_layer_max_mipmap_level (pipeline, 0, mipmap_level); bare_region_visible = bare_region_visible || draw_texture (self, monitor->fbo, pipeline, diff -Nru mutter-3.36.1/src/compositor/meta-compositor-server.c mutter-3.36.9/src/compositor/meta-compositor-server.c --- mutter-3.36.1/src/compositor/meta-compositor-server.c 2020-03-30 19:29:39.293885200 +0000 +++ mutter-3.36.9/src/compositor/meta-compositor-server.c 2021-03-15 23:07:33.284500400 +0000 @@ -39,6 +39,13 @@ { } +static int64_t +meta_compositor_server_monotonic_to_high_res_xserver_time (MetaCompositor *compositor, + int64_t monotonic_time_us) +{ + return meta_translate_to_high_res_xserver_time (monotonic_time_us); +} + MetaCompositorServer * meta_compositor_server_new (MetaDisplay *display) { @@ -59,4 +66,6 @@ compositor_class->manage = meta_compositor_server_manage; compositor_class->unmanage = meta_compositor_server_unmanage; + compositor_class->monotonic_to_high_res_xserver_time = + meta_compositor_server_monotonic_to_high_res_xserver_time; } diff -Nru mutter-3.36.1/src/compositor/meta-compositor-x11.c mutter-3.36.9/src/compositor/meta-compositor-x11.c --- mutter-3.36.1/src/compositor/meta-compositor-x11.c 2020-03-30 19:29:39.293885200 +0000 +++ mutter-3.36.9/src/compositor/meta-compositor-x11.c 2021-03-15 23:07:33.285500300 +0000 @@ -43,6 +43,10 @@ gboolean have_x11_sync_object; MetaWindow *unredirected_window; + + gboolean xserver_uses_monotonic_clock; + int64_t xserver_time_query_time_us; + int64_t xserver_time_offset_us; }; G_DEFINE_TYPE (MetaCompositorX11, meta_compositor_x11, META_TYPE_COMPOSITOR) @@ -101,6 +105,32 @@ } static void +determine_server_clock_source (MetaCompositorX11 *compositor_x11) +{ + MetaCompositor *compositor = META_COMPOSITOR (compositor_x11); + MetaDisplay *display = meta_compositor_get_display (compositor); + MetaX11Display *x11_display = display->x11_display; + uint32_t server_time_ms; + int64_t server_time_us; + int64_t translated_monotonic_now_us; + + server_time_ms = meta_x11_display_get_current_time_roundtrip (x11_display); + server_time_us = ms2us (server_time_ms); + translated_monotonic_now_us = + meta_translate_to_high_res_xserver_time (g_get_monotonic_time ()); + + /* If the server time offset is within a second of the monotonic time, we + * assume that they are identical. This seems like a big margin, but we want + * to be as robust as possible even if the system is under load and our + * processing of the server response is delayed. + */ + if (ABS (server_time_us - translated_monotonic_now_us) < s2us (1)) + compositor_x11->xserver_uses_monotonic_clock = TRUE; + else + compositor_x11->xserver_uses_monotonic_clock = FALSE; +} + +static void meta_compositor_x11_manage (MetaCompositor *compositor) { MetaCompositorX11 *compositor_x11 = META_COMPOSITOR_X11 (compositor); @@ -109,6 +139,8 @@ MetaBackend *backend = meta_get_backend (); Window xwindow; + determine_server_clock_source (compositor_x11); + meta_x11_display_set_cm_selection (display->x11_display); compositor_x11->output = display->x11_display->composite_overlay_window; @@ -338,6 +370,37 @@ parent_class->remove_window (compositor, window); } +static int64_t +meta_compositor_x11_monotonic_to_high_res_xserver_time (MetaCompositor *compositor, + int64_t monotonic_time_us) +{ + MetaCompositorX11 *compositor_x11 = META_COMPOSITOR_X11 (compositor); + int64_t now_us; + + if (compositor_x11->xserver_uses_monotonic_clock) + return meta_translate_to_high_res_xserver_time (monotonic_time_us); + + now_us = g_get_monotonic_time (); + + if (compositor_x11->xserver_time_query_time_us == 0 || + now_us > (compositor_x11->xserver_time_query_time_us + s2us (10))) + { + MetaDisplay *display = meta_compositor_get_display (compositor); + MetaX11Display *x11_display = display->x11_display; + uint32_t xserver_time_ms; + int64_t xserver_time_us; + + compositor_x11->xserver_time_query_time_us = now_us; + + xserver_time_ms = + meta_x11_display_get_current_time_roundtrip (x11_display); + xserver_time_us = ms2us (xserver_time_ms); + compositor_x11->xserver_time_offset_us = xserver_time_us - now_us; + } + + return monotonic_time_us + compositor_x11->xserver_time_offset_us; +} + Window meta_compositor_x11_get_output_xwindow (MetaCompositorX11 *compositor_x11) { @@ -384,4 +447,6 @@ compositor_class->pre_paint = meta_compositor_x11_pre_paint; compositor_class->post_paint = meta_compositor_x11_post_paint; compositor_class->remove_window = meta_compositor_x11_remove_window; + compositor_class->monotonic_to_high_res_xserver_time = + meta_compositor_x11_monotonic_to_high_res_xserver_time; } diff -Nru mutter-3.36.1/src/compositor/meta-dnd-actor.c mutter-3.36.9/src/compositor/meta-dnd-actor.c --- mutter-3.36.1/src/compositor/meta-dnd-actor.c 2020-03-30 19:29:39.294885200 +0000 +++ mutter-3.36.9/src/compositor/meta-dnd-actor.c 2021-03-15 23:07:33.285500300 +0000 @@ -28,6 +28,7 @@ #include "config.h" #include "compositor/meta-dnd-actor-private.h" +#include "compositor/meta-window-actor-private.h" #include "clutter/clutter.h" @@ -206,16 +207,29 @@ if (CLUTTER_ACTOR_IS_VISIBLE (self->drag_origin)) { + MetaWindowActor *origin_actor; float anchor_x, anchor_y; graphene_point_t dest; + int origin_geometry_scale; + int feedback_geometry_scale; clutter_actor_get_transformed_position (self->drag_origin, &dest.x, &dest.y); + + origin_actor = meta_window_actor_from_actor (self->drag_origin); + g_return_if_fail (origin_actor); + origin_geometry_scale = + meta_window_actor_get_geometry_scale (origin_actor); + meta_feedback_actor_get_anchor (META_FEEDBACK_ACTOR (self), &anchor_x, &anchor_y); + feedback_geometry_scale = + meta_feedback_actor_get_geometry_scale (META_FEEDBACK_ACTOR (self)); - dest.x += self->drag_start_x - anchor_x; - dest.y += self->drag_start_y - anchor_y; + dest.x += ((self->drag_start_x * origin_geometry_scale) - + (anchor_x * feedback_geometry_scale)); + dest.y += ((self->drag_start_y * origin_geometry_scale) - + (anchor_y * feedback_geometry_scale)); clutter_actor_set_position (actor, dest.x, dest.y); } diff -Nru mutter-3.36.1/src/compositor/meta-feedback-actor.c mutter-3.36.9/src/compositor/meta-feedback-actor.c --- mutter-3.36.1/src/compositor/meta-feedback-actor.c 2020-03-30 19:29:39.294885200 +0000 +++ mutter-3.36.9/src/compositor/meta-feedback-actor.c 2021-03-15 23:07:33.285500300 +0000 @@ -44,6 +44,8 @@ float anchor_y; float pos_x; float pos_y; + + int geometry_scale; }; G_DEFINE_TYPE_WITH_PRIVATE (MetaFeedbackActor, meta_feedback_actor, CLUTTER_TYPE_ACTOR) @@ -65,8 +67,10 @@ MetaFeedbackActorPrivate *priv = meta_feedback_actor_get_instance_private (self); clutter_actor_set_position (CLUTTER_ACTOR (self), - priv->pos_x - priv->anchor_x, - priv->pos_y - priv->anchor_y); + priv->pos_x - + (priv->anchor_x * priv->geometry_scale), + priv->pos_y - + (priv->anchor_y * priv->geometry_scale)); } static void @@ -249,3 +253,31 @@ clutter_event_get_position (event, &point); meta_feedback_actor_set_position (self, point.x, point.y); } + +void +meta_feedback_actor_set_geometry_scale (MetaFeedbackActor *self, + int geometry_scale) +{ + MetaFeedbackActorPrivate *priv = + meta_feedback_actor_get_instance_private (self); + CoglMatrix child_transform; + + if (priv->geometry_scale == geometry_scale) + return; + + priv->geometry_scale = geometry_scale; + + cogl_matrix_init_identity (&child_transform); + cogl_matrix_scale (&child_transform, geometry_scale, geometry_scale, 1); + clutter_actor_set_child_transform (CLUTTER_ACTOR (self), + &child_transform); +} + +int +meta_feedback_actor_get_geometry_scale (MetaFeedbackActor *self) +{ + MetaFeedbackActorPrivate *priv = + meta_feedback_actor_get_instance_private (self); + + return priv->geometry_scale; +} diff -Nru mutter-3.36.1/src/compositor/meta-feedback-actor-private.h mutter-3.36.9/src/compositor/meta-feedback-actor-private.h --- mutter-3.36.1/src/compositor/meta-feedback-actor-private.h 2020-03-30 19:29:39.294885200 +0000 +++ mutter-3.36.9/src/compositor/meta-feedback-actor-private.h 2021-03-15 23:07:33.285500300 +0000 @@ -62,4 +62,9 @@ void meta_feedback_actor_update (MetaFeedbackActor *self, const ClutterEvent *event); +void meta_feedback_actor_set_geometry_scale (MetaFeedbackActor *self, + int geometry_scale); + +int meta_feedback_actor_get_geometry_scale (MetaFeedbackActor *self); + #endif /* META_FEEDBACK_ACTOR_PRIVATE_H */ diff -Nru mutter-3.36.1/src/compositor/meta-shaped-texture.c mutter-3.36.9/src/compositor/meta-shaped-texture.c --- mutter-3.36.1/src/compositor/meta-shaped-texture.c 2020-03-30 19:29:39.295885000 +0000 +++ mutter-3.36.9/src/compositor/meta-shaped-texture.c 2021-03-15 23:07:33.286500200 +0000 @@ -87,6 +87,9 @@ /* The region containing only fully opaque pixels */ cairo_region_t *opaque_region; + /* MetaCullable regions, see that documentation for more details */ + cairo_region_t *clip_region; + gboolean size_invalid; MetaMonitorTransform transform; gboolean has_viewport_src_rect; @@ -214,6 +217,15 @@ update_size (stex); } +void +meta_shaped_texture_set_clip_region (MetaShapedTexture *stex, + cairo_region_t *clip_region) +{ + g_clear_pointer (&stex->clip_region, cairo_region_destroy); + if (clip_region) + stex->clip_region = cairo_region_reference (clip_region); +} + static void meta_shaped_texture_reset_pipelines (MetaShapedTexture *stex) { @@ -239,6 +251,7 @@ meta_shaped_texture_reset_pipelines (stex); g_clear_pointer (&stex->opaque_region, cairo_region_destroy); + g_clear_pointer (&stex->clip_region, cairo_region_destroy); g_clear_pointer (&stex->snippet, cogl_object_unref); @@ -390,17 +403,14 @@ CoglContext *ctx) { CoglPipeline *pipeline; - CoglColor color; if (stex->unblended_pipeline) return stex->unblended_pipeline; pipeline = cogl_pipeline_copy (get_base_pipeline (stex, ctx)); - cogl_color_init_from_4ub (&color, 255, 255, 255, 255); - cogl_pipeline_set_blend (pipeline, - "RGBA = ADD (SRC_COLOR, 0)", - NULL); - cogl_pipeline_set_color (pipeline, &color); + cogl_pipeline_set_layer_combine (pipeline, 0, + "RGBA = REPLACE (TEXTURE)", + NULL); stex->unblended_pipeline = pipeline; @@ -585,12 +595,19 @@ if (use_opaque_region) { - blended_tex_region = cairo_region_create_rectangle (&content_rect); + if (stex->clip_region) + blended_tex_region = cairo_region_copy (stex->clip_region); + else + blended_tex_region = cairo_region_create_rectangle (&content_rect); + cairo_region_subtract (blended_tex_region, stex->opaque_region); } else { - blended_tex_region = NULL; + if (stex->clip_region) + blended_tex_region = cairo_region_reference (stex->clip_region); + else + blended_tex_region = NULL; } /* Limit to how many separate rectangles we'll draw; beyond this just @@ -612,10 +629,21 @@ /* First, paint the unblended parts, which are part of the opaque region. */ if (use_opaque_region) { + cairo_region_t *region; int n_rects; int i; - if (!cairo_region_is_empty (stex->opaque_region)) + if (stex->clip_region) + { + region = cairo_region_copy (stex->clip_region); + cairo_region_intersect (region, stex->opaque_region); + } + else + { + region = cairo_region_reference (stex->opaque_region); + } + + if (!cairo_region_is_empty (region)) { CoglPipeline *opaque_pipeline; @@ -623,16 +651,18 @@ cogl_pipeline_set_layer_texture (opaque_pipeline, 0, paint_tex); cogl_pipeline_set_layer_filters (opaque_pipeline, 0, filter, filter); - n_rects = cairo_region_num_rectangles (stex->opaque_region); + n_rects = cairo_region_num_rectangles (region); for (i = 0; i < n_rects; i++) { cairo_rectangle_int_t rect; - cairo_region_get_rectangle (stex->opaque_region, i, &rect); + cairo_region_get_rectangle (region, i, &rect); paint_clipped_rectangle_node (stex, root_node, opaque_pipeline, &rect, alloc); } } + + cairo_region_destroy (region); } /* Now, go ahead and paint the blended parts. */ @@ -757,6 +787,9 @@ CoglTexture *paint_tex = NULL; uint8_t opacity; + if (stex->clip_region && cairo_region_is_empty (stex->clip_region)) + return; + /* The GL EXT_texture_from_pixmap extension does allow for it to be * used together with SGIS_generate_mipmap, however this is very * rarely supported. Also, even when it is supported there diff -Nru mutter-3.36.1/src/compositor/meta-shaped-texture-private.h mutter-3.36.9/src/compositor/meta-shaped-texture-private.h --- mutter-3.36.1/src/compositor/meta-shaped-texture-private.h 2020-03-30 19:29:39.295885000 +0000 +++ mutter-3.36.9/src/compositor/meta-shaped-texture-private.h 2021-03-15 23:07:33.286500200 +0000 @@ -66,4 +66,7 @@ int meta_shaped_texture_get_width (MetaShapedTexture *stex); int meta_shaped_texture_get_height (MetaShapedTexture *stex); +void meta_shaped_texture_set_clip_region (MetaShapedTexture *stex, + cairo_region_t *clip_region); + #endif diff -Nru mutter-3.36.1/src/compositor/meta-surface-actor.c mutter-3.36.9/src/compositor/meta-surface-actor.c --- mutter-3.36.1/src/compositor/meta-surface-actor.c 2020-03-30 19:29:39.296885300 +0000 +++ mutter-3.36.9/src/compositor/meta-surface-actor.c 2021-03-15 23:07:33.287500400 +0000 @@ -34,7 +34,6 @@ cairo_region_t *input_region; /* MetaCullable regions, see that documentation for more details */ - cairo_region_t *clip_region; cairo_region_t *unobscured_region; /* Freeze/thaw accounting */ @@ -58,6 +57,12 @@ static guint signals[LAST_SIGNAL]; +typedef enum +{ + IN_STAGE_PERSPECTIVE, + IN_ACTOR_PERSPECTIVE +} ScalePerspectiveType; + static cairo_region_t * effective_unobscured_region (MetaSurfaceActor *surface_actor) { @@ -79,18 +84,39 @@ } static cairo_region_t* -get_scaled_region (MetaSurfaceActor *surface_actor, - cairo_region_t *region) +get_scaled_region (MetaSurfaceActor *surface_actor, + cairo_region_t *region, + ScalePerspectiveType scale_perspective) { MetaWindowActor *window_actor; + cairo_region_t *scaled_region; int geometry_scale; + float x, y; window_actor = meta_window_actor_from_actor (CLUTTER_ACTOR (surface_actor)); geometry_scale = meta_window_actor_get_geometry_scale (window_actor); - return meta_region_scale_double (region, - 1.0 / geometry_scale, - META_ROUNDING_STRATEGY_GROW); + clutter_actor_get_position (CLUTTER_ACTOR (surface_actor), &x, &y); + cairo_region_translate (region, x, y); + + switch (scale_perspective) + { + case IN_STAGE_PERSPECTIVE: + scaled_region = meta_region_scale_double (region, + geometry_scale, + META_ROUNDING_STRATEGY_GROW); + break; + case IN_ACTOR_PERSPECTIVE: + scaled_region = meta_region_scale_double (region, + 1.0 / geometry_scale, + META_ROUNDING_STRATEGY_GROW); + break; + } + + cairo_region_translate (region, -x, -y); + cairo_region_translate (scaled_region, -x, -y); + + return scaled_region; } static void @@ -120,8 +146,9 @@ .height = height, }; - priv->unobscured_region = - get_scaled_region (surface_actor, unobscured_region); + priv->unobscured_region = get_scaled_region (surface_actor, + unobscured_region, + IN_ACTOR_PERSPECTIVE); cairo_region_intersect_rectangle (priv->unobscured_region, &bounds); } @@ -134,30 +161,23 @@ { MetaSurfaceActorPrivate *priv = meta_surface_actor_get_instance_private (surface_actor); + MetaShapedTexture *stex = priv->texture; - g_clear_pointer (&priv->clip_region, cairo_region_destroy); - if (clip_region) + if (clip_region && !cairo_region_is_empty (clip_region)) { - if (cairo_region_is_empty (clip_region)) - priv->clip_region = cairo_region_reference (clip_region); - else - priv->clip_region = get_scaled_region (surface_actor, clip_region); - } -} + cairo_region_t *region; -static void -meta_surface_actor_paint (ClutterActor *actor, - ClutterPaintContext *paint_context) -{ - MetaSurfaceActor *surface_actor = META_SURFACE_ACTOR (actor); - MetaSurfaceActorPrivate *priv = - meta_surface_actor_get_instance_private (surface_actor); - - if (priv->clip_region && cairo_region_is_empty (priv->clip_region)) - return; + region = get_scaled_region (surface_actor, + clip_region, + IN_ACTOR_PERSPECTIVE); + meta_shaped_texture_set_clip_region (stex, region); - CLUTTER_ACTOR_CLASS (meta_surface_actor_parent_class)->paint (actor, - paint_context); + cairo_region_destroy (region); + } + else + { + meta_shaped_texture_set_clip_region (stex, clip_region); + } } static void @@ -227,7 +247,6 @@ g_clear_object (&priv->texture); set_unobscured_region (self, NULL); - set_clip_region (self, NULL); G_OBJECT_CLASS (meta_surface_actor_parent_class)->dispose (object); } @@ -239,7 +258,6 @@ ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass); object_class->dispose = meta_surface_actor_dispose; - actor_class->paint = meta_surface_actor_paint; actor_class->pick = meta_surface_actor_pick; actor_class->get_paint_volume = meta_surface_actor_get_paint_volume; @@ -279,48 +297,23 @@ if (opacity == 0xff) { - MetaWindowActor *window_actor; - cairo_region_t *scaled_opaque_region; cairo_region_t *opaque_region; - int geometry_scale; - float x, y; + cairo_region_t *scaled_opaque_region; opaque_region = meta_shaped_texture_get_opaque_region (priv->texture); - if (opaque_region) - { - cairo_region_reference (opaque_region); - } - else if (meta_shaped_texture_is_opaque (priv->texture)) - { - cairo_rectangle_int_t rect; - rect = (cairo_rectangle_int_t) { - .width = meta_shaped_texture_get_width (priv->texture), - .height = meta_shaped_texture_get_height (priv->texture) - }; + if (!opaque_region) + return; - opaque_region = cairo_region_create_rectangle (&rect); - } - else - { - return; - } - - window_actor = meta_window_actor_from_actor (CLUTTER_ACTOR (surface_actor)); - geometry_scale = meta_window_actor_get_geometry_scale (window_actor); - clutter_actor_get_position (CLUTTER_ACTOR (surface_actor), &x, &y); - - cairo_region_translate (opaque_region, x, y); - scaled_opaque_region = meta_region_scale (opaque_region, geometry_scale); - cairo_region_translate (scaled_opaque_region, -x, -y); - cairo_region_translate (opaque_region, -x, -y); + scaled_opaque_region = get_scaled_region (surface_actor, + opaque_region, + IN_STAGE_PERSPECTIVE); if (unobscured_region) cairo_region_subtract (unobscured_region, scaled_opaque_region); if (clip_region) cairo_region_subtract (clip_region, scaled_opaque_region); - cairo_region_destroy (opaque_region); cairo_region_destroy (scaled_opaque_region); } } @@ -419,9 +412,12 @@ return priv->texture; } -static void +void meta_surface_actor_update_area (MetaSurfaceActor *self, - int x, int y, int width, int height) + int x, + int y, + int width, + int height) { MetaSurfaceActorPrivate *priv = meta_surface_actor_get_instance_private (self); @@ -546,9 +542,6 @@ } META_SURFACE_ACTOR_GET_CLASS (self)->process_damage (self, x, y, width, height); - - if (meta_surface_actor_is_visible (self)) - meta_surface_actor_update_area (self, x, y, width, height); } void @@ -557,12 +550,6 @@ META_SURFACE_ACTOR_GET_CLASS (self)->pre_paint (self); } -gboolean -meta_surface_actor_is_visible (MetaSurfaceActor *self) -{ - return META_SURFACE_ACTOR_GET_CLASS (self)->is_visible (self); -} - void meta_surface_actor_set_frozen (MetaSurfaceActor *self, gboolean frozen) diff -Nru mutter-3.36.1/src/compositor/meta-surface-actor.h mutter-3.36.9/src/compositor/meta-surface-actor.h --- mutter-3.36.1/src/compositor/meta-surface-actor.h 2020-03-30 19:29:39.296885300 +0000 +++ mutter-3.36.9/src/compositor/meta-surface-actor.h 2021-03-15 23:07:33.287500400 +0000 @@ -25,7 +25,6 @@ void (* process_damage) (MetaSurfaceActor *actor, int x, int y, int width, int height); void (* pre_paint) (MetaSurfaceActor *actor); - gboolean (* is_visible) (MetaSurfaceActor *actor); gboolean (* is_opaque) (MetaSurfaceActor *actor); }; @@ -34,6 +33,12 @@ MetaShapedTexture *meta_surface_actor_get_texture (MetaSurfaceActor *self); +void meta_surface_actor_update_area (MetaSurfaceActor *self, + int x, + int y, + int width, + int height); + gboolean meta_surface_actor_is_obscured (MetaSurfaceActor *self); void meta_surface_actor_set_input_region (MetaSurfaceActor *self, @@ -45,7 +50,6 @@ void meta_surface_actor_process_damage (MetaSurfaceActor *actor, int x, int y, int width, int height); void meta_surface_actor_pre_paint (MetaSurfaceActor *actor); -gboolean meta_surface_actor_is_visible (MetaSurfaceActor *actor); gboolean meta_surface_actor_is_opaque (MetaSurfaceActor *actor); gboolean meta_surface_actor_is_frozen (MetaSurfaceActor *actor); diff -Nru mutter-3.36.1/src/compositor/meta-surface-actor-wayland.c mutter-3.36.9/src/compositor/meta-surface-actor-wayland.c --- mutter-3.36.1/src/compositor/meta-surface-actor-wayland.c 2020-03-30 19:29:39.295885000 +0000 +++ mutter-3.36.9/src/compositor/meta-surface-actor-wayland.c 2021-03-15 23:07:33.287500400 +0000 @@ -42,7 +42,6 @@ MetaSurfaceActor parent; MetaWaylandSurface *surface; - struct wl_list frame_callback_list; }; G_DEFINE_TYPE (MetaSurfaceActorWayland, @@ -56,6 +55,7 @@ int width, int height) { + meta_surface_actor_update_area (actor, x, y, width, height); } static void @@ -64,14 +64,6 @@ } static gboolean -meta_surface_actor_wayland_is_visible (MetaSurfaceActor *actor) -{ - /* TODO: ensure that the buffer isn't NULL, implement - * wayland mapping semantics */ - return TRUE; -} - -static gboolean meta_surface_actor_wayland_is_opaque (MetaSurfaceActor *actor) { MetaShapedTexture *stex = meta_surface_actor_get_texture (actor); @@ -79,37 +71,10 @@ return meta_shaped_texture_is_opaque (stex); } -void -meta_surface_actor_wayland_add_frame_callbacks (MetaSurfaceActorWayland *self, - struct wl_list *frame_callbacks) -{ - wl_list_insert_list (&self->frame_callback_list, frame_callbacks); -} - -static void -meta_surface_actor_wayland_paint (ClutterActor *actor, - ClutterPaintContext *paint_context) -{ - MetaSurfaceActorWayland *self = META_SURFACE_ACTOR_WAYLAND (actor); - - if (self->surface && - !meta_surface_actor_is_obscured (META_SURFACE_ACTOR (actor))) - { - MetaWaylandCompositor *compositor = self->surface->compositor; - - wl_list_insert_list (&compositor->frame_callbacks, &self->frame_callback_list); - wl_list_init (&self->frame_callback_list); - } - - CLUTTER_ACTOR_CLASS (meta_surface_actor_wayland_parent_class)->paint (actor, - paint_context); -} - static void meta_surface_actor_wayland_dispose (GObject *object) { MetaSurfaceActorWayland *self = META_SURFACE_ACTOR_WAYLAND (object); - MetaWaylandFrameCallback *cb, *next; MetaShapedTexture *stex; stex = meta_surface_actor_get_texture (META_SURFACE_ACTOR (self)); @@ -123,9 +88,6 @@ self->surface = NULL; } - wl_list_for_each_safe (cb, next, &self->frame_callback_list, link) - wl_resource_destroy (cb->resource); - G_OBJECT_CLASS (meta_surface_actor_wayland_parent_class)->dispose (object); } @@ -133,14 +95,10 @@ meta_surface_actor_wayland_class_init (MetaSurfaceActorWaylandClass *klass) { MetaSurfaceActorClass *surface_actor_class = META_SURFACE_ACTOR_CLASS (klass); - ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass); GObjectClass *object_class = G_OBJECT_CLASS (klass); - actor_class->paint = meta_surface_actor_wayland_paint; - surface_actor_class->process_damage = meta_surface_actor_wayland_process_damage; surface_actor_class->pre_paint = meta_surface_actor_wayland_pre_paint; - surface_actor_class->is_visible = meta_surface_actor_wayland_is_visible; surface_actor_class->is_opaque = meta_surface_actor_wayland_is_opaque; object_class->dispose = meta_surface_actor_wayland_dispose; @@ -158,7 +116,6 @@ g_assert (meta_is_wayland_compositor ()); - wl_list_init (&self->frame_callback_list); self->surface = surface; g_object_add_weak_pointer (G_OBJECT (self->surface), (gpointer *) &self->surface); diff -Nru mutter-3.36.1/src/compositor/meta-surface-actor-x11.c mutter-3.36.9/src/compositor/meta-surface-actor-x11.c --- mutter-3.36.1/src/compositor/meta-surface-actor-x11.c 2020-03-30 19:29:39.296885300 +0000 +++ mutter-3.36.9/src/compositor/meta-surface-actor-x11.c 2021-03-15 23:07:33.287500400 +0000 @@ -181,8 +181,8 @@ } } -static gboolean -is_visible (MetaSurfaceActorX11 *self) +gboolean +meta_surface_actor_x11_is_visible (MetaSurfaceActorX11 *self) { return (self->pixmap != None) && !self->unredirected; } @@ -212,11 +212,12 @@ self->does_full_damage = TRUE; } - if (!is_visible (self)) + if (!meta_surface_actor_x11_is_visible (self)) return; cogl_texture_pixmap_x11_update_area (COGL_TEXTURE_PIXMAP_X11 (self->texture), x, y, width, height); + meta_surface_actor_update_area (actor, x, y, width, height); } static void @@ -239,13 +240,6 @@ } static gboolean -meta_surface_actor_x11_is_visible (MetaSurfaceActor *actor) -{ - MetaSurfaceActorX11 *self = META_SURFACE_ACTOR_X11 (actor); - return is_visible (self); -} - -static gboolean meta_surface_actor_x11_is_opaque (MetaSurfaceActor *actor) { MetaSurfaceActorX11 *self = META_SURFACE_ACTOR_X11 (actor); @@ -358,7 +352,6 @@ surface_actor_class->process_damage = meta_surface_actor_x11_process_damage; surface_actor_class->pre_paint = meta_surface_actor_x11_pre_paint; - surface_actor_class->is_visible = meta_surface_actor_x11_is_visible; surface_actor_class->is_opaque = meta_surface_actor_x11_is_opaque; } diff -Nru mutter-3.36.1/src/compositor/meta-surface-actor-x11.h mutter-3.36.9/src/compositor/meta-surface-actor-x11.h --- mutter-3.36.1/src/compositor/meta-surface-actor-x11.h 2020-03-30 19:29:39.296885300 +0000 +++ mutter-3.36.9/src/compositor/meta-surface-actor-x11.h 2021-03-15 23:07:33.287500400 +0000 @@ -53,6 +53,8 @@ gboolean meta_surface_actor_x11_is_unredirected (MetaSurfaceActorX11 *self); +gboolean meta_surface_actor_x11_is_visible (MetaSurfaceActorX11 *self); + G_END_DECLS #endif /* __META_SURFACE_ACTOR_X11_H__ */ diff -Nru mutter-3.36.1/src/compositor/meta-window-actor.c mutter-3.36.9/src/compositor/meta-window-actor.c --- mutter-3.36.1/src/compositor/meta-window-actor.c 2020-03-30 19:29:39.297885200 +0000 +++ mutter-3.36.9/src/compositor/meta-window-actor.c 2021-03-15 23:07:33.289500200 +0000 @@ -1300,6 +1300,7 @@ cogl_color_init_from_4ub (&clear_color, 0, 0, 0, 0); cogl_framebuffer_clear (framebuffer, COGL_BUFFER_BIT_COLOR, &clear_color); cogl_framebuffer_orthographic (framebuffer, 0, 0, width, height, 0, 1.0); + cogl_framebuffer_set_viewport (framebuffer, 0, 0, width, height); meta_rectangle_scale_double (bounds, resource_scale, META_ROUNDING_STRATEGY_GROW, diff -Nru mutter-3.36.1/src/compositor/meta-window-actor-wayland.c mutter-3.36.9/src/compositor/meta-window-actor-wayland.c --- mutter-3.36.1/src/compositor/meta-window-actor-wayland.c 2020-03-30 19:29:39.297885200 +0000 +++ mutter-3.36.9/src/compositor/meta-window-actor-wayland.c 2021-03-15 23:07:33.288500300 +0000 @@ -139,29 +139,6 @@ { } -static gboolean -meta_window_actor_wayland_get_paint_volume (ClutterActor *actor, - ClutterPaintVolume *volume) -{ - MetaSurfaceActor *surface; - - surface = meta_window_actor_get_surface (META_WINDOW_ACTOR (actor)); - if (surface) - { - ClutterActor *surface_actor = CLUTTER_ACTOR (surface); - const ClutterPaintVolume *child_volume; - - child_volume = clutter_actor_get_transformed_paint_volume (surface_actor, - actor); - if (!child_volume) - return FALSE; - - clutter_paint_volume_union (volume, child_volume); - } - - return TRUE; -} - static void meta_window_actor_wayland_update_regions (MetaWindowActor *actor) { @@ -171,9 +148,6 @@ meta_window_actor_wayland_class_init (MetaWindowActorWaylandClass *klass) { MetaWindowActorClass *window_actor_class = META_WINDOW_ACTOR_CLASS (klass); - ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass); - - actor_class->get_paint_volume = meta_window_actor_wayland_get_paint_volume; window_actor_class->assign_surface_actor = meta_window_actor_wayland_assign_surface_actor; window_actor_class->frame_complete = meta_window_actor_wayland_frame_complete; diff -Nru mutter-3.36.1/src/compositor/meta-window-actor-x11.c mutter-3.36.9/src/compositor/meta-window-actor-x11.c --- mutter-3.36.1/src/compositor/meta-window-actor-x11.c 2020-03-30 19:29:39.297885200 +0000 +++ mutter-3.36.9/src/compositor/meta-window-actor-x11.c 2021-03-15 23:07:33.288500300 +0000 @@ -85,6 +85,8 @@ cairo_region_t *shape_region; /* The region we should clip to when painting the shadow */ cairo_region_t *shadow_clip; + /* The frame region */ + cairo_region_t *frame_bounds; /* Extracted size-invariant shape used for shadows */ MetaWindowShape *shadow_shape; @@ -157,12 +159,14 @@ meta_window_actor_get_meta_window (META_WINDOW_ACTOR (actor_x11)); MetaDisplay *display = meta_window_get_display (window); Display *xdisplay = meta_x11_display_get_xdisplay (display->x11_display); + int64_t now_us; XClientMessageEvent ev = { 0, }; + now_us = g_get_monotonic_time (); frame->frame_drawn_time = - meta_compositor_monotonic_time_to_server_time (display, - g_get_monotonic_time ()); + meta_compositor_monotonic_to_high_res_xserver_time (display->compositor, + now_us); actor_x11->frame_drawn_time = frame->frame_drawn_time; ev.type = ClientMessage; @@ -202,9 +206,12 @@ if (presentation_time != 0) { - int64_t presentation_time_server = - meta_compositor_monotonic_time_to_server_time (display, - presentation_time); + MetaCompositor *compositor = display->compositor; + int64_t presentation_time_server; + + presentation_time_server = + meta_compositor_monotonic_to_high_res_xserver_time (compositor, + presentation_time); int64_t presentation_time_offset = presentation_time_server - frame->frame_drawn_time; if (presentation_time_offset == 0) presentation_time_offset = 1; @@ -277,6 +284,7 @@ meta_window_actor_get_meta_window (META_WINDOW_ACTOR (actor_x11)); MetaDisplay *display = meta_window_get_display (window); MetaLogicalMonitor *logical_monitor; + int64_t now_us; int64_t current_time; float refresh_rate; int interval, offset; @@ -301,9 +309,10 @@ refresh_rate = 60.0f; } + now_us = g_get_monotonic_time (); current_time = - meta_compositor_monotonic_time_to_server_time (display, - g_get_monotonic_time ()); + meta_compositor_monotonic_to_high_res_xserver_time (display->compositor, + now_us); interval = (int) (1000000 / refresh_rate) * 6; offset = MAX (0, actor_x11->frame_drawn_time + interval - current_time) / 1000; @@ -702,11 +711,8 @@ if (clip_shadow_under_window (actor_x11)) { - cairo_region_t *frame_bounds; - - frame_bounds = meta_window_get_frame_bounds (window); - if (frame_bounds) - cairo_region_subtract (actor_x11->shadow_clip, frame_bounds); + if (actor_x11->frame_bounds) + cairo_region_subtract (actor_x11->shadow_clip, actor_x11->frame_bounds); } } else @@ -1127,6 +1133,17 @@ } static void +update_frame_bounds (MetaWindowActorX11 *actor_x11) +{ + MetaWindow *window = + meta_window_actor_get_meta_window (META_WINDOW_ACTOR (actor_x11)); + + g_clear_pointer (&actor_x11->frame_bounds, cairo_region_destroy); + actor_x11->frame_bounds = + cairo_region_copy (meta_window_get_frame_bounds (window)); +} + +static void update_regions (MetaWindowActorX11 *actor_x11) { if (!actor_x11->needs_reshape) @@ -1194,9 +1211,11 @@ meta_surface_actor_pre_paint (surface); - if (!meta_surface_actor_is_visible (surface)) + if (!META_IS_SURFACE_ACTOR_X11 (surface) || + !meta_surface_actor_x11_is_visible (META_SURFACE_ACTOR_X11 (surface))) return; + update_frame_bounds (actor_x11); check_needs_reshape (actor_x11); check_needs_shadow (actor_x11); } @@ -1250,15 +1269,13 @@ */ if (!clip && clip_shadow_under_window (actor_x11)) { - cairo_region_t *frame_bounds; cairo_rectangle_int_t bounds; get_shadow_bounds (actor_x11, appears_focused, &bounds); clip = cairo_region_create_rectangle (&bounds); - frame_bounds = meta_window_get_frame_bounds (window); - if (frame_bounds) - cairo_region_subtract (clip, frame_bounds); + if (actor_x11->frame_bounds) + cairo_region_subtract (clip, actor_x11->frame_bounds); } framebuffer = clutter_paint_context_get_framebuffer (paint_context); @@ -1545,6 +1562,7 @@ g_clear_pointer (&actor_x11->shape_region, cairo_region_destroy); g_clear_pointer (&actor_x11->shadow_clip, cairo_region_destroy); + g_clear_pointer (&actor_x11->frame_bounds, cairo_region_destroy); g_clear_pointer (&actor_x11->shadow_class, g_free); g_clear_pointer (&actor_x11->focused_shadow, meta_shadow_unref); @@ -1620,8 +1638,8 @@ self->shadow_factory = meta_shadow_factory_get_default (); self->shadow_factory_changed_handler_id = - g_signal_connect (self->shadow_factory, - "changed", - G_CALLBACK (invalidate_shadow), - self); + g_signal_connect_swapped (self->shadow_factory, + "changed", + G_CALLBACK (invalidate_shadow), + self); } diff -Nru mutter-3.36.1/src/compositor/region-utils.c mutter-3.36.9/src/compositor/region-utils.c --- mutter-3.36.1/src/compositor/region-utils.c 2020-03-30 19:29:39.298885000 +0000 +++ mutter-3.36.9/src/compositor/region-utils.c 2021-03-15 23:07:33.290500200 +0000 @@ -26,6 +26,15 @@ #include +#define META_REGION_MAX_STACK_RECTS 256 + +#define META_REGION_CREATE_RECTANGLE_ARRAY_SCOPED(n_rects, rects) \ + g_autofree cairo_rectangle_int_t *G_PASTE(__n, __LINE__) = NULL; \ + if (n_rects < META_REGION_MAX_STACK_RECTS) \ + rects = g_newa (cairo_rectangle_int_t, n_rects); \ + else \ + rects = G_PASTE(__n, __LINE__) = g_new (cairo_rectangle_int_t, n_rects); + /* MetaRegionBuilder */ /* Various algorithms in this file require unioning together a set of rectangles @@ -187,12 +196,11 @@ g_return_val_if_fail (scale > 0.0, NULL); - if (scale == 1.0) + if (G_APPROX_VALUE (scale, 1.f, FLT_EPSILON)) return cairo_region_copy (region); n_rects = cairo_region_num_rectangles (region); - - rects = g_malloc (sizeof(cairo_rectangle_int_t) * n_rects); + META_REGION_CREATE_RECTANGLE_ARRAY_SCOPED (n_rects, rects); for (i = 0; i < n_rects; i++) { cairo_region_get_rectangle (region, i, &rects[i]); @@ -203,8 +211,6 @@ scaled_region = cairo_region_create_rectangles (rects, n_rects); - g_free (rects); - return scaled_region; } @@ -219,8 +225,7 @@ return cairo_region_copy (region); n_rects = cairo_region_num_rectangles (region); - - rects = g_malloc (sizeof(cairo_rectangle_int_t) * n_rects); + META_REGION_CREATE_RECTANGLE_ARRAY_SCOPED (n_rects, rects); for (i = 0; i < n_rects; i++) { cairo_region_get_rectangle (region, i, &rects[i]); @@ -232,8 +237,6 @@ scaled_region = cairo_region_create_rectangles (rects, n_rects); - g_free (rects); - return scaled_region; } @@ -389,8 +392,7 @@ return cairo_region_copy (region); n_rects = cairo_region_num_rectangles (region); - - rects = g_new0 (cairo_rectangle_int_t, n_rects); + META_REGION_CREATE_RECTANGLE_ARRAY_SCOPED (n_rects, rects); for (i = 0; i < n_rects; i++) { cairo_region_get_rectangle (region, i, &rects[i]); @@ -404,8 +406,6 @@ transformed_region = cairo_region_create_rectangles (rects, n_rects); - g_free (rects); - return transformed_region; } @@ -419,14 +419,17 @@ cairo_rectangle_int_t *rects; cairo_region_t *viewport_region; - if (src_rect->size.width == dst_width && - src_rect->size.height == dst_height && - roundf (src_rect->origin.x) == src_rect->origin.x && - roundf (src_rect->origin.y) == src_rect->origin.y) + if (G_APPROX_VALUE (src_rect->size.width, dst_width, FLT_EPSILON) && + G_APPROX_VALUE (src_rect->size.height, dst_height, FLT_EPSILON) && + G_APPROX_VALUE (roundf (src_rect->origin.x), + src_rect->origin.x, FLT_EPSILON) && + G_APPROX_VALUE (roundf (src_rect->origin.y), + src_rect->origin.y, FLT_EPSILON)) { viewport_region = cairo_region_copy (region); - if (src_rect->origin.x != 0 || src_rect->origin.y != 0) + if (G_APPROX_VALUE (src_rect->origin.x, 0, FLT_EPSILON) || + G_APPROX_VALUE (src_rect->origin.y, 0, FLT_EPSILON)) { cairo_region_translate (viewport_region, (int) src_rect->origin.x, @@ -437,8 +440,7 @@ } n_rects = cairo_region_num_rectangles (region); - - rects = g_new0 (cairo_rectangle_int_t, n_rects); + META_REGION_CREATE_RECTANGLE_ARRAY_SCOPED (n_rects, rects); for (i = 0; i < n_rects; i++) { cairo_region_get_rectangle (region, i, &rects[i]); @@ -452,7 +454,5 @@ viewport_region = cairo_region_create_rectangles (rects, n_rects); - g_free (rects); - return viewport_region; } diff -Nru mutter-3.36.1/src/core/constraints.c mutter-3.36.9/src/core/constraints.c --- mutter-3.36.1/src/core/constraints.c 2020-03-30 19:29:39.300885200 +0000 +++ mutter-3.36.9/src/core/constraints.c 2021-03-15 23:07:33.291500000 +0000 @@ -469,6 +469,16 @@ info->entire_monitor.width, info->entire_monitor.height); } +static MetaRectangle * +get_start_rect_for_resize (MetaWindow *window, + ConstraintInfo *info) +{ + if (!info->is_user_action && info->action_type == ACTION_MOVE_AND_RESIZE) + return &info->current; + else + return &info->orig; +} + static void place_window_if_needed(MetaWindow *window, ConstraintInfo *info) @@ -1368,13 +1378,7 @@ new_height = client_rect.height; } - /* Figure out what original rect to pass to meta_rectangle_resize_with_gravity - * See bug 448183 - */ - if (info->action_type == ACTION_MOVE_AND_RESIZE) - start_rect = &info->current; - else - start_rect = &info->orig; + start_rect = get_start_rect_for_resize (window, info); /* Resize to the new size */ meta_rectangle_resize_with_gravity (start_rect, @@ -1424,13 +1428,7 @@ new_width = CLAMP (info->current.width, min_size.width, max_size.width); new_height = CLAMP (info->current.height, min_size.height, max_size.height); - /* Figure out what original rect to pass to meta_rectangle_resize_with_gravity - * See bug 448183 - */ - if (info->action_type == ACTION_MOVE_AND_RESIZE) - start_rect = &info->current; - else - start_rect = &info->orig; + start_rect = get_start_rect_for_resize (window, info); meta_rectangle_resize_with_gravity (start_rect, &info->current, @@ -1570,13 +1568,7 @@ new_height = client_rect.height; } - /* Figure out what original rect to pass to meta_rectangle_resize_with_gravity - * See bug 448183 - */ - if (info->action_type == ACTION_MOVE_AND_RESIZE) - start_rect = &info->current; - else - start_rect = &info->orig; + start_rect = get_start_rect_for_resize (window, info); meta_rectangle_resize_with_gravity (start_rect, &info->current, diff -Nru mutter-3.36.1/src/core/events.c mutter-3.36.9/src/core/events.c --- mutter-3.36.1/src/core/events.c 2020-03-30 19:29:39.301885100 +0000 +++ mutter-3.36.9/src/core/events.c 2021-03-15 23:07:33.294500000 +0000 @@ -206,7 +206,6 @@ G_GNUC_UNUSED gboolean bypass_wayland = FALSE; MetaGestureTracker *gesture_tracker; ClutterEventSequence *sequence; - ClutterInputDevice *source; sequence = clutter_event_get_event_sequence (event); @@ -272,10 +271,17 @@ } } - source = clutter_event_get_source_device (event); + if (event->type != CLUTTER_DEVICE_ADDED && + event->type != CLUTTER_DEVICE_REMOVED) + { + ClutterInputDevice *source; + + handle_idletime_for_event (event); + source = clutter_event_get_source_device (event); - if (source) - meta_backend_update_last_device (backend, source); + if (source) + meta_backend_update_last_device (backend, source); + } #ifdef HAVE_WAYLAND if (meta_is_wayland_compositor () && event->type == CLUTTER_MOTION) @@ -302,8 +308,6 @@ } #endif - handle_idletime_for_event (event); - window = get_window_for_event (display, event); display->current_time = event->any.time; diff -Nru mutter-3.36.1/src/core/keybindings.c mutter-3.36.9/src/core/keybindings.c --- mutter-3.36.1/src/core/keybindings.c 2020-03-30 19:29:39.302885000 +0000 +++ mutter-3.36.9/src/core/keybindings.c 2021-03-15 23:07:33.295500000 +0000 @@ -2129,7 +2129,7 @@ return TRUE; } else if (event->type == CLUTTER_KEY_PRESS && - (event->modifier_state & ~(IGNORED_MODIFIERS)) == 0 && + ((event->modifier_state & ~(IGNORED_MODIFIERS)) & CLUTTER_MODIFIER_MASK) == 0 && resolved_key_combo_has_keycode (resolved_key_combo, event->hardware_keycode)) { diff -Nru mutter-3.36.1/src/core/main.c mutter-3.36.9/src/core/main.c --- mutter-3.36.1/src/core/main.c 2020-03-30 19:29:39.303885000 +0000 +++ mutter-3.36.9/src/core/main.c 2021-03-15 23:07:33.295500000 +0000 @@ -586,11 +586,6 @@ g_irepository_prepend_search_path (MUTTER_PKGLIBDIR); #endif -#ifdef HAVE_WAYLAND - if (meta_is_wayland_compositor ()) - meta_wayland_pre_clutter_init (); -#endif - /* NB: When running as a hybrid wayland compositor we run our own headless X * server so the user can't control the X display to connect too. */ if (!meta_is_wayland_compositor ()) @@ -598,14 +593,6 @@ meta_init_backend (backend_gtype); - meta_clutter_init (); - -#ifdef HAVE_WAYLAND - /* Bring up Wayland. This also launches Xwayland and sets DISPLAY as well... */ - if (meta_is_wayland_compositor ()) - meta_wayland_init (); -#endif - meta_set_syncing (opt_sync || (g_getenv ("MUTTER_SYNC") != NULL)); if (opt_replace_wm) diff -Nru mutter-3.36.1/src/core/meta-clipboard-manager.c mutter-3.36.9/src/core/meta-clipboard-manager.c --- mutter-3.36.1/src/core/meta-clipboard-manager.c 2020-03-30 19:29:39.303885000 +0000 +++ mutter-3.36.9/src/core/meta-clipboard-manager.c 2021-03-15 23:07:33.296500000 +0000 @@ -152,6 +152,7 @@ display->saved_clipboard); g_set_object (&display->selection_source, new_owner); meta_selection_set_owner (selection, selection_type, new_owner); + g_object_unref (new_owner); } } @@ -170,6 +171,7 @@ { MetaSelection *selection; + g_clear_object (&display->selection_source); g_clear_pointer (&display->saved_clipboard, g_bytes_unref); g_clear_pointer (&display->saved_clipboard_mimetype, g_free); selection = meta_display_get_selection (display); diff -Nru mutter-3.36.1/src/core/meta-selection.c mutter-3.36.9/src/core/meta-selection.c --- mutter-3.36.1/src/core/meta-selection.c 2020-03-30 19:29:39.305885000 +0000 +++ mutter-3.36.9/src/core/meta-selection.c 2021-03-15 23:07:33.297500100 +0000 @@ -21,6 +21,7 @@ #include "config.h" +#include "core/meta-selection-private.h" #include "meta/meta-selection.h" typedef struct TransferRequest TransferRequest; @@ -50,6 +51,9 @@ G_DEFINE_TYPE (MetaSelection, meta_selection, G_TYPE_OBJECT) +static void read_selection_source_async (GTask *task, + TransferRequest *request); + static void meta_selection_dispose (GObject *object) { @@ -216,6 +220,7 @@ GAsyncResult *result, GTask *task) { + TransferRequest *request; GError *error = NULL; g_output_stream_write_bytes_finish (stream, result, &error); @@ -226,8 +231,17 @@ return; } - g_task_return_boolean (task, TRUE); - g_object_unref (task); + request = g_task_get_task_data (task); + + if (request->len > 0) + { + read_selection_source_async (task, request); + } + else + { + g_task_return_boolean (task, TRUE); + g_object_unref (task); + } } static void @@ -246,8 +260,26 @@ g_object_unref (task); return; } + else if (g_bytes_get_size (bytes) == 0) + { + g_task_return_boolean (task, TRUE); + g_object_unref (task); + return; + } request = g_task_get_task_data (task); + + if (request->len < g_bytes_get_size (bytes)) + { + GBytes *copy; + + /* Trim content */ + copy = g_bytes_new_from_bytes (bytes, 0, request->len); + g_bytes_unref (bytes); + bytes = copy; + } + + request->len -= g_bytes_get_size (bytes); g_output_stream_write_bytes_async (request->ostream, bytes, G_PRIORITY_DEFAULT, @@ -258,6 +290,18 @@ } static void +read_selection_source_async (GTask *task, + TransferRequest *request) +{ + g_input_stream_read_bytes_async (request->istream, + (gsize) request->len, + G_PRIORITY_DEFAULT, + g_task_get_cancellable (task), + (GAsyncReadyCallback) read_cb, + task); +} + +static void source_read_cb (MetaSelectionSource *source, GAsyncResult *result, GTask *task) @@ -290,12 +334,7 @@ } else { - g_input_stream_read_bytes_async (request->istream, - (gsize) request->len, - G_PRIORITY_DEFAULT, - g_task_get_cancellable (task), - (GAsyncReadyCallback) read_cb, - task); + read_selection_source_async (task, request); } } @@ -364,3 +403,13 @@ return g_task_propagate_boolean (G_TASK (result), error); } + +MetaSelectionSource * +meta_selection_get_current_owner (MetaSelection *selection, + MetaSelectionType selection_type) +{ + g_return_val_if_fail (META_IS_SELECTION (selection), NULL); + g_return_val_if_fail (selection_type < META_N_SELECTION_TYPES, NULL); + + return selection->owners[selection_type]; +} diff -Nru mutter-3.36.1/src/core/meta-selection-private.h mutter-3.36.9/src/core/meta-selection-private.h --- mutter-3.36.1/src/core/meta-selection-private.h 1970-01-01 00:00:00.000000000 +0000 +++ mutter-3.36.9/src/core/meta-selection-private.h 2021-03-15 23:07:33.297500100 +0000 @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2020 Red Hat + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + * + * Written by: + * Carlos Garnacho + */ + +#ifndef META_SELECTION_PRIVATE_H +#define META_SELECTION_PRIVATE_H + +#include "meta/meta-selection.h" + +MetaSelectionSource * + meta_selection_get_current_owner (MetaSelection *selection, + MetaSelectionType selection_type); + +#endif /* META_SELECTION_PRIVATE_H */ diff -Nru mutter-3.36.1/src/core/window.c mutter-3.36.9/src/core/window.c --- mutter-3.36.1/src/core/window.c 2020-03-30 19:29:39.310885000 +0000 +++ mutter-3.36.9/src/core/window.c 2021-03-15 23:07:33.301499800 +0000 @@ -1796,6 +1796,7 @@ static gboolean idle_calc_showing (gpointer data) { + MetaDisplay *display = meta_get_display (); GSList *tmp; GSList *copy; GSList *should_show; @@ -1866,6 +1867,8 @@ tmp = tmp->next; } + meta_stack_freeze (display->stack); + tmp = should_show; while (tmp != NULL) { @@ -1890,6 +1893,8 @@ tmp = tmp->next; } + meta_stack_thaw (display->stack); + tmp = copy; while (tmp != NULL) { @@ -3275,6 +3280,15 @@ #endif } +static void +meta_window_maybe_apply_size_hints (MetaWindow *window, + MetaRectangle *target_rect) +{ + meta_window_frame_rect_to_client_rect (window, target_rect, target_rect); + ensure_size_hints_satisfied (target_rect, &window->size_hints); + meta_window_client_rect_to_frame_rect (window, target_rect, target_rect); +} + void meta_window_unmaximize (MetaWindow *window, MetaMaximizeFlags directions) @@ -3372,9 +3386,7 @@ /* Window's size hints may have changed while maximized, making * saved_rect invalid. #329152 */ - meta_window_frame_rect_to_client_rect (window, &target_rect, &target_rect); - ensure_size_hints_satisfied (&target_rect, &window->size_hints); - meta_window_client_rect_to_frame_rect (window, &target_rect, &target_rect); + meta_window_maybe_apply_size_hints (window, &target_rect); meta_compositor_size_change_window (window->display->compositor, window, META_SIZE_CHANGE_UNMAXIMIZE, @@ -3529,9 +3541,7 @@ /* Window's size hints may have changed while maximized, making * saved_rect invalid. #329152 */ - meta_window_frame_rect_to_client_rect (window, &target_rect, &target_rect); - ensure_size_hints_satisfied (&target_rect, &window->size_hints); - meta_window_client_rect_to_frame_rect (window, &target_rect, &target_rect); + meta_window_maybe_apply_size_hints (window, &target_rect); /* Need to update window->has_resize_func before we move_resize() */ @@ -3751,6 +3761,8 @@ meta_window_focus (window, timestamp); else meta_workspace_activate_with_focus (window->workspace, window, timestamp); + + meta_window_check_alive (window, timestamp); } /* This function exists since most of the functionality in window_activate @@ -4790,8 +4802,6 @@ return; } - meta_window_check_alive (window, timestamp); - META_WINDOW_GET_CLASS (window)->focus (window, timestamp); if (window->display->event_route == META_EVENT_ROUTE_NORMAL) @@ -6250,9 +6260,9 @@ gboolean force) { int dx, dy; - int new_w, new_h; MetaGravity gravity; - MetaRectangle old; + MetaRectangle new_rect; + MetaRectangle old_rect; double remaining = 0; window->display->grab_latest_motion_x = x; @@ -6271,8 +6281,8 @@ dy *= 2; } - new_w = window->display->grab_anchor_window_pos.width; - new_h = window->display->grab_anchor_window_pos.height; + new_rect.width = window->display->grab_anchor_window_pos.width; + new_rect.height = window->display->grab_anchor_window_pos.height; /* Don't bother doing anything if no move has been specified. (This * happens often, even in keyboard resizing, due to the warping of the @@ -6301,14 +6311,16 @@ } if (window->display->grab_op & META_GRAB_OP_WINDOW_DIR_EAST) - new_w += dx; + new_rect.width += dx; else if (window->display->grab_op & META_GRAB_OP_WINDOW_DIR_WEST) - new_w -= dx; + new_rect.width -= dx; if (window->display->grab_op & META_GRAB_OP_WINDOW_DIR_SOUTH) - new_h += dy; + new_rect.height += dy; else if (window->display->grab_op & META_GRAB_OP_WINDOW_DIR_NORTH) - new_h -= dy; + new_rect.height -= dy; + + meta_window_maybe_apply_size_hints (window, &new_rect); /* If we're waiting for a request for _NET_WM_SYNC_REQUEST, we'll * resize the window when the window responds, or when we time @@ -6338,7 +6350,7 @@ /* Remove any scheduled compensation events */ g_clear_handle_id (&window->display->grab_resize_timeout_id, g_source_remove); - meta_window_get_frame_rect (window, &old); + meta_window_get_frame_rect (window, &old_rect); /* One sided resizing ought to actually be one-sided, despite the fact that * aspect ratio windows don't interact nicely with the above stuff. So, @@ -6346,10 +6358,10 @@ */ if ((window->display->grab_op & (META_GRAB_OP_WINDOW_DIR_WEST | META_GRAB_OP_WINDOW_DIR_EAST)) == 0) - new_w = old.width; + new_rect.width = old_rect.width; if ((window->display->grab_op & (META_GRAB_OP_WINDOW_DIR_NORTH | META_GRAB_OP_WINDOW_DIR_SOUTH)) == 0) - new_h = old.height; + new_rect.height = old_rect.height; /* compute gravity of client during operation */ gravity = meta_resize_gravity_from_grab_op (window->display->grab_op); @@ -6357,17 +6369,20 @@ /* Do any edge resistance/snapping */ meta_window_edge_resistance_for_resize (window, - &new_w, - &new_h, + &new_rect.width, + &new_rect.height, gravity, update_resize_timeout, snap, FALSE); - meta_window_resize_frame_with_gravity (window, TRUE, new_w, new_h, gravity); + meta_window_resize_frame_with_gravity (window, TRUE, + new_rect.width, new_rect.height, + gravity); /* Store the latest resize time, if we actually resized. */ - if (window->rect.width != old.width || window->rect.height != old.height) + if (window->rect.width != old_rect.width || + window->rect.height != old_rect.height) window->display->grab_last_moveresize_time = g_get_real_time (); } @@ -8314,6 +8329,9 @@ gfloat x, y; guint button; + if (window->unmanaging) + return; + if (event->type != CLUTTER_BUTTON_PRESS && event->type != CLUTTER_TOUCH_BEGIN) return; @@ -8349,6 +8367,7 @@ "Focusing %s due to button %u press (display.c)\n", window->desc, button); meta_window_focus (window, event->any.time); + meta_window_check_alive (window, event->any.time); } else /* However, do allow terminals to lose focus due to new @@ -8570,6 +8589,8 @@ gboolean meta_window_can_ping (MetaWindow *window) { + g_return_val_if_fail (!window->unmanaging, FALSE); + return META_WINDOW_GET_CLASS (window)->can_ping (window); } @@ -8579,6 +8600,12 @@ return META_WINDOW_GET_CLASS (window)->is_stackable (window); } +gboolean +meta_window_is_focus_async (MetaWindow *window) +{ + return META_WINDOW_GET_CLASS (window)->is_focus_async (window); +} + MetaStackLayer meta_window_calculate_layer (MetaWindow *window) { diff -Nru mutter-3.36.1/src/core/window-private.h mutter-3.36.9/src/core/window-private.h --- mutter-3.36.1/src/core/window-private.h 2020-03-30 19:29:39.308884900 +0000 +++ mutter-3.36.9/src/core/window-private.h 2021-03-15 23:07:33.300500000 +0000 @@ -611,6 +611,7 @@ gboolean (*is_stackable) (MetaWindow *window); gboolean (*can_ping) (MetaWindow *window); gboolean (*are_updates_frozen) (MetaWindow *window); + gboolean (*is_focus_async) (MetaWindow *window); MetaStackLayer (*calculate_layer) (MetaWindow *window); @@ -879,4 +880,5 @@ gboolean meta_window_shortcuts_inhibited (MetaWindow *window, ClutterInputDevice *source); gboolean meta_window_is_stackable (MetaWindow *window); +gboolean meta_window_is_focus_async (MetaWindow *window); #endif diff -Nru mutter-3.36.1/src/core/workspace.c mutter-3.36.9/src/core/workspace.c --- mutter-3.36.1/src/core/workspace.c 2020-03-30 19:29:39.311884900 +0000 +++ mutter-3.36.9/src/core/workspace.c 2021-03-15 23:07:33.302499800 +0000 @@ -1332,7 +1332,10 @@ { MetaWorkspaceFocusableAncestorData *data = user_data; - if (!window->unmanaging && meta_window_is_focusable (window) && + if (!window->unmanaging && + window->mapped && + !window->hidden && + meta_window_is_focusable (window) && meta_window_located_on_workspace (window, data->workspace) && meta_window_showing_on_its_workspace (window)) { @@ -1343,6 +1346,38 @@ return TRUE; } +static gboolean +try_to_set_focus_and_check (MetaWindow *window, + MetaWindow *not_this_one, + uint32_t timestamp) +{ + meta_window_focus (window, timestamp); + + /* meta_focus_window() will not change focus for clients using the + * "globally active input" model of input handling, hence defeating + * the assumption that focus should be changed for such windows. + * See https://tronche.com/gui/x/icccm/sec-4.html#s-4.1.7 + */ + if (meta_window_is_focus_async (window)) + return TRUE; + + /* meta_window_focus() does not guarantee that focus will end up + * where we expect, it can fail for various reasons, better check + * it did not actually changed or even left focus to the window we + * explicitly want to avoid. + */ + if (not_this_one && + meta_display_get_focus_window (window->display) == not_this_one) + { + meta_warning ("Failed to focus window %s while avoiding %s", + window->desc, not_this_one->desc); + + return FALSE; + } + + return TRUE; +} + /* Focus ancestor of not_this_one if there is one */ static void focus_ancestor_or_top_window (MetaWorkspace *workspace, @@ -1376,13 +1411,14 @@ "Focusing %s, ancestor of %s\n", ancestor->desc, not_this_one->desc); - meta_window_focus (ancestor, timestamp); - - /* Also raise the window if in click-to-focus */ - if (meta_prefs_get_focus_mode () == G_DESKTOP_FOCUS_MODE_CLICK) - meta_window_raise (ancestor); + if (try_to_set_focus_and_check (ancestor, not_this_one, timestamp)) + { + /* Also raise the window if in click-to-focus */ + if (meta_prefs_get_focus_mode () == G_DESKTOP_FOCUS_MODE_CLICK) + meta_window_raise (ancestor); - return; + return; + } } } @@ -1394,18 +1430,19 @@ { meta_topic (META_DEBUG_FOCUS, "Focusing workspace MRU window %s\n", window->desc); + if (try_to_set_focus_and_check (window, not_this_one, timestamp)) + { + /* Also raise the window if in click-to-focus */ + if (meta_prefs_get_focus_mode () == G_DESKTOP_FOCUS_MODE_CLICK) + meta_window_raise (window); - meta_window_focus (window, timestamp); - - /* Also raise the window if in click-to-focus */ - if (meta_prefs_get_focus_mode () == G_DESKTOP_FOCUS_MODE_CLICK) - meta_window_raise (window); - } - else - { - meta_topic (META_DEBUG_FOCUS, "No MRU window to focus found; focusing no_focus_window.\n"); - meta_display_unset_input_focus (workspace->display, timestamp); + return; + } } + + meta_topic (META_DEBUG_FOCUS, + "No MRU window to focus found; focusing no_focus_window."); + meta_display_unset_input_focus (workspace->display, timestamp); } /** diff -Nru mutter-3.36.1/src/meson.build mutter-3.36.9/src/meson.build --- mutter-3.36.1/src/meson.build 2020-03-30 19:29:39.312884800 +0000 +++ mutter-3.36.9/src/meson.build 2021-03-15 23:07:33.302499800 +0000 @@ -495,7 +495,22 @@ 'wayland/meta-wayland-cursor-surface.h', 'wayland/meta-wayland-data-device.c', 'wayland/meta-wayland-data-device.h', - 'wayland/meta-wayland-data-device-private.h', + 'wayland/meta-wayland-data-device-primary.c', + 'wayland/meta-wayland-data-device-primary.h', + 'wayland/meta-wayland-data-device-primary-legacy.c', + 'wayland/meta-wayland-data-device-primary-legacy.h', + 'wayland/meta-wayland-data-offer.c', + 'wayland/meta-wayland-data-offer.h', + 'wayland/meta-wayland-data-offer-primary.c', + 'wayland/meta-wayland-data-offer-primary.h', + 'wayland/meta-wayland-data-offer-primary-legacy.c', + 'wayland/meta-wayland-data-offer-primary-legacy.h', + 'wayland/meta-wayland-data-source.c', + 'wayland/meta-wayland-data-source.h', + 'wayland/meta-wayland-data-source-primary.c', + 'wayland/meta-wayland-data-source-primary.h', + 'wayland/meta-wayland-data-source-primary-legacy.c', + 'wayland/meta-wayland-data-source-primary-legacy.h', 'wayland/meta-wayland-dma-buf.c', 'wayland/meta-wayland-dma-buf.h', 'wayland/meta-wayland-dnd-surface.c', @@ -790,6 +805,7 @@ ['linux-dmabuf', 'unstable', 'v1', ], ['pointer-constraints', 'unstable', 'v1', ], ['pointer-gestures', 'unstable', 'v1', ], + ['primary-selection', 'unstable', 'v1', ], ['relative-pointer', 'unstable', 'v1', ], ['tablet', 'unstable', 'v2', ], ['text-input', 'unstable', 'v3', ], diff -Nru mutter-3.36.1/src/tests/clutter/conform/actor-pick.c mutter-3.36.9/src/tests/clutter/conform/actor-pick.c --- mutter-3.36.1/src/tests/clutter/conform/actor-pick.c 2020-03-30 19:29:39.319884500 +0000 +++ mutter-3.36.9/src/tests/clutter/conform/actor-pick.c 2021-03-15 23:07:33.307499600 +0000 @@ -67,6 +67,9 @@ } else if (test_num == 2) { + ClutterActorBox over_actor_box = + CLUTTER_ACTOR_BOX_INIT (0, 0, STAGE_WIDTH, STAGE_HEIGHT); + /* Make the actor visible but set a clip so that only some of the actors are accessible */ clutter_actor_show (over_actor); @@ -76,6 +79,11 @@ state->actor_width * (ACTORS_X - 4), state->actor_height * (ACTORS_Y - 4)); + /* Only allocated actors can be picked, so force an allocation + * of the overlay actor here. + */ + clutter_actor_allocate (over_actor, &over_actor_box, 0); + if (g_test_verbose ()) g_print ("Clipped covering actor:\n"); } @@ -175,10 +183,10 @@ for (y = 0; y < ACTORS_Y; y++) for (x = 0; x < ACTORS_X; x++) { - ClutterColor color = { x * 255 / (ACTORS_X - 1), - y * 255 / (ACTORS_Y - 1), - 128, 255 }; - ClutterActor *rect = clutter_rectangle_new_with_color (&color); + ClutterColor color = { x * 255 / (ACTORS_X - 1), + y * 255 / (ACTORS_Y - 1), + 128, 255 }; + ClutterActor *rect = clutter_rectangle_new_with_color (&color); clutter_actor_set_position (rect, x * state.actor_width, @@ -187,9 +195,9 @@ state.actor_width, state.actor_height); - clutter_actor_add_child (state.stage, rect); + clutter_actor_add_child (state.stage, rect); - state.actors[y * ACTORS_X + x] = rect; + state.actors[y * ACTORS_X + x] = rect; } clutter_actor_show (state.stage); diff -Nru mutter-3.36.1/src/tests/clutter/interactive/test-cogl-multitexture.c mutter-3.36.9/src/tests/clutter/interactive/test-cogl-multitexture.c --- mutter-3.36.1/src/tests/clutter/interactive/test-cogl-multitexture.c 2020-03-30 19:29:39.322884600 +0000 +++ mutter-3.36.9/src/tests/clutter/interactive/test-cogl-multitexture.c 2021-03-15 23:07:33.310499700 +0000 @@ -112,7 +112,7 @@ GError *error = NULL; ClutterActor *stage; ClutterColor stage_color = { 0x61, 0x56, 0x56, 0xff }; - TestMultiLayerMaterialState *state = g_new0 (TestMultiLayerMaterialState, 1); + g_autofree TestMultiLayerMaterialState *state = g_new0 (TestMultiLayerMaterialState, 1); gfloat stage_w, stage_h; gchar **files; gfloat tex_coords[] = diff -Nru mutter-3.36.1/src/tests/monitor-configs/lid-scale.xml mutter-3.36.9/src/tests/monitor-configs/lid-scale.xml --- mutter-3.36.1/src/tests/monitor-configs/lid-scale.xml 1970-01-01 00:00:00.000000000 +0000 +++ mutter-3.36.9/src/tests/monitor-configs/lid-scale.xml 2021-03-15 23:07:33.317499400 +0000 @@ -0,0 +1,23 @@ + + + + 0 + 0 + yes + 2 + + + eDP-1 + MetaProduct's Inc. + MetaMonitor + 0x123456 + + + 1920 + 1080 + 60.000495910644531 + + + + + diff -Nru mutter-3.36.1/src/tests/monitor-unit-tests.c mutter-3.36.9/src/tests/monitor-unit-tests.c --- mutter-3.36.1/src/tests/monitor-unit-tests.c 2020-03-30 19:29:39.331884400 +0000 +++ mutter-3.36.9/src/tests/monitor-unit-tests.c 2021-03-15 23:07:33.319499500 +0000 @@ -2869,6 +2869,116 @@ } static void +meta_test_monitor_lid_scaled_closed_opened (void) +{ + MonitorTestCase test_case = { + .setup = { + .modes = { + { + .width = 1920, + .height = 1080, + .refresh_rate = 60.000495910644531 + } + }, + .n_modes = 1, + .outputs = { + { + .crtc = 0, + .modes = { 0 }, + .n_modes = 1, + .preferred_mode = 0, + .possible_crtcs = { 0 }, + .n_possible_crtcs = 1, + .width_mm = 222, + .height_mm = 125, + .is_laptop_panel = TRUE + }, + }, + .n_outputs = 1, + .crtcs = { + { + .current_mode = 0 + }, + }, + .n_crtcs = 1 + }, + + .expect = { + .monitors = { + { + .outputs = { 0 }, + .n_outputs = 1, + .modes = { + { + .width = 1920, + .height = 1080, + .refresh_rate = 60.000495910644531, + .crtc_modes = { + { + .output = 0, + .crtc_mode = 0 + } + } + } + }, + .n_modes = 1, + .current_mode = 0, + .width_mm = 222, + .height_mm = 125, + } + }, + .n_monitors = 1, + .logical_monitors = { + { + .monitors = { 0 }, + .n_monitors = 1, + .layout = { .x = 0, .y = 0, .width = 960, .height = 540 }, + .scale = 2 + } + }, + .n_logical_monitors = 1, + .primary_logical_monitor = 0, + .n_outputs = 1, + .crtcs = { + { + .current_mode = 0, + } + }, + .n_crtcs = 1, + .n_tiled_monitors = 0, + .screen_width = 960, + .screen_height = 540 + } + }; + MetaMonitorTestSetup *test_setup; + MetaBackend *backend = meta_get_backend (); + MetaMonitorManager *monitor_manager = + meta_backend_get_monitor_manager (backend); + + if (!meta_is_stage_views_enabled ()) + { + g_test_skip ("Not using stage views"); + return; + } + + test_setup = create_monitor_test_setup (&test_case, + MONITOR_TEST_FLAG_NONE); + set_custom_monitor_config ("lid-scale.xml"); + emulate_hotplug (test_setup); + check_monitor_configuration (&test_case); + + meta_backend_test_set_is_lid_closed (META_BACKEND_TEST (backend), TRUE); + meta_monitor_manager_lid_is_closed_changed (monitor_manager); + + check_monitor_configuration (&test_case); + + meta_backend_test_set_is_lid_closed (META_BACKEND_TEST (backend), FALSE); + meta_monitor_manager_lid_is_closed_changed (monitor_manager); + + check_monitor_configuration (&test_case); +} + +static void meta_test_monitor_no_outputs (void) { MonitorTestCase test_case = { @@ -4828,12 +4938,13 @@ .current_mode = 1, .transform = META_MONITOR_TRANSFORM_90, .x = 1024, - .y = 400, + .y = 0, }, { .current_mode = 1, .transform = META_MONITOR_TRANSFORM_90, .x = 1024, + .y = 400, } }, .n_crtcs = 3, @@ -4860,6 +4971,198 @@ } static void +meta_test_monitor_custom_second_rotated_nonnative_tiled_config (void) +{ + MonitorTestCase test_case = { + .setup = { + .modes = { + { + .width = 1024, + .height = 768, + .refresh_rate = 60.000495910644531 + }, + { + .width = 400, + .height = 600, + .refresh_rate = 60.000495910644531 + } + }, + .n_modes = 2, + .outputs = { + { + .crtc = 0, + .modes = { 0 }, + .n_modes = 1, + .preferred_mode = 0, + .possible_crtcs = { 0 }, + .n_possible_crtcs = 1, + .width_mm = 222, + .height_mm = 125, + }, + { + .crtc = -1, + .modes = { 1 }, + .n_modes = 1, + .preferred_mode = 1, + .possible_crtcs = { 1, 2 }, + .n_possible_crtcs = 2, + .width_mm = 222, + .height_mm = 125, + .tile_info = { + .group_id = 1, + .max_h_tiles = 2, + .max_v_tiles = 1, + .loc_h_tile = 0, + .loc_v_tile = 0, + .tile_w = 400, + .tile_h = 600 + } + }, + { + .crtc = -1, + .modes = { 1 }, + .n_modes = 1, + .preferred_mode = 1, + .possible_crtcs = { 1, 2 }, + .n_possible_crtcs = 2, + .width_mm = 222, + .height_mm = 125, + .tile_info = { + .group_id = 1, + .max_h_tiles = 2, + .max_v_tiles = 1, + .loc_h_tile = 1, + .loc_v_tile = 0, + .tile_w = 400, + .tile_h = 600 + } + } + }, + .n_outputs = 3, + .crtcs = { + { + .current_mode = -1 + }, + { + .current_mode = -1 + }, + { + .current_mode = -1 + } + }, + .n_crtcs = 3 + }, + + .expect = { + .monitors = { + { + .outputs = { 0 }, + .n_outputs = 1, + .modes = { + { + .width = 1024, + .height = 768, + .refresh_rate = 60.000495910644531, + .crtc_modes = { + { + .output = 0, + .crtc_mode = 0 + } + } + } + }, + .n_modes = 1, + .current_mode = 0, + .width_mm = 222, + .height_mm = 125, + }, + { + .outputs = { 1, 2 }, + .n_outputs = 2, + .modes = { + { + .width = 800, + .height = 600, + .refresh_rate = 60.000495910644531, + .crtc_modes = { + { + .output = 1, + .crtc_mode = 1, + }, + { + .output = 2, + .crtc_mode = 1, + } + } + } + }, + .n_modes = 1, + .current_mode = 0, + .width_mm = 222, + .height_mm = 125, + } + }, + .n_monitors = 2, + .logical_monitors = { + { + .monitors = { 0 }, + .n_monitors = 1, + .layout = { .x = 0, .y = 256, .width = 1024, .height = 768 }, + .scale = 1 + }, + { + .monitors = { 1 }, + .n_monitors = 1, + .layout = { .x = 1024, .y = 0, .width = 600, .height = 800 }, + .scale = 1, + .transform = META_MONITOR_TRANSFORM_90 + } + }, + .n_logical_monitors = 2, + .primary_logical_monitor = 0, + .n_outputs = 3, + .crtcs = { + { + .current_mode = 0, + .y = 256, + }, + { + .current_mode = 1, + .transform = META_MONITOR_TRANSFORM_NORMAL, + .x = 1024, + .y = 0, + }, + { + .current_mode = 1, + .transform = META_MONITOR_TRANSFORM_NORMAL, + .x = 1024, + .y = 400, + } + }, + .n_crtcs = 3, + .n_tiled_monitors = 1, + .screen_width = 1024 + 600, + .screen_height = 1024 + } + }; + MetaMonitorTestSetup *test_setup; + MetaBackend *backend = meta_get_backend (); + MetaMonitorManager *monitor_manager = + meta_backend_get_monitor_manager (backend); + MetaMonitorManagerTest *monitor_manager_test = + META_MONITOR_MANAGER_TEST (monitor_manager); + + meta_monitor_manager_test_set_handles_transforms (monitor_manager_test, + FALSE); + + test_setup = create_monitor_test_setup (&test_case, + MONITOR_TEST_FLAG_NONE); + set_custom_monitor_config ("second-rotated-tiled.xml"); + emulate_hotplug (test_setup); + check_monitor_configuration (&test_case); +} + +static void meta_test_monitor_custom_second_rotated_nonnative_config (void) { MonitorTestCase test_case = { @@ -6058,6 +6361,8 @@ meta_test_monitor_lid_closed_no_external); add_monitor_test ("/backends/monitor/lid-closed-with-hotplugged-external", meta_test_monitor_lid_closed_with_hotplugged_external); + add_monitor_test ("/backends/monitor/lid-scaled-closed-opened", + meta_test_monitor_lid_scaled_closed_opened); add_monitor_test ("/backends/monitor/no-outputs", meta_test_monitor_no_outputs); add_monitor_test ("/backends/monitor/underscanning-config", @@ -6093,6 +6398,8 @@ meta_test_monitor_custom_second_rotated_config); add_monitor_test ("/backends/monitor/custom/second-rotated-tiled-config", meta_test_monitor_custom_second_rotated_tiled_config); + add_monitor_test ("/backends/monitor/custom/second-rotated-nonnative-tiled-config", + meta_test_monitor_custom_second_rotated_nonnative_tiled_config); add_monitor_test ("/backends/monitor/custom/second-rotated-nonnative-config", meta_test_monitor_custom_second_rotated_nonnative_config); add_monitor_test ("/backends/monitor/custom/interlaced-config", diff -Nru mutter-3.36.1/src/tests/test-utils.c mutter-3.36.9/src/tests/test-utils.c --- mutter-3.36.1/src/tests/test-utils.c 2020-03-30 19:29:39.333884200 +0000 +++ mutter-3.36.9/src/tests/test-utils.c 2021-03-15 23:07:33.320499400 +0000 @@ -427,7 +427,7 @@ MetaWindowClientType type, GError **error) { - TestClient *client = g_new0 (TestClient, 1); + TestClient *client; GSubprocessLauncher *launcher; GSubprocess *subprocess; MetaWaylandCompositor *compositor; @@ -462,6 +462,7 @@ if (!subprocess) return NULL; + client = g_new0 (TestClient, 1); client->type = type; client->id = g_strdup (id); client->cancellable = g_cancellable_new (); diff -Nru mutter-3.36.1/src/wayland/meta-selection-source-wayland-private.h mutter-3.36.9/src/wayland/meta-selection-source-wayland-private.h --- mutter-3.36.1/src/wayland/meta-selection-source-wayland-private.h 2020-03-30 19:29:39.337884200 +0000 +++ mutter-3.36.9/src/wayland/meta-selection-source-wayland-private.h 2021-03-15 23:07:33.323499200 +0000 @@ -26,7 +26,6 @@ #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 ()) diff -Nru mutter-3.36.1/src/wayland/meta-wayland-actor-surface.c mutter-3.36.9/src/wayland/meta-wayland-actor-surface.c --- mutter-3.36.1/src/wayland/meta-wayland-actor-surface.c 2020-03-30 19:29:39.338884000 +0000 +++ mutter-3.36.9/src/wayland/meta-wayland-actor-surface.c 2021-03-15 23:07:33.323499200 +0000 @@ -104,9 +104,15 @@ MetaWaylandSurface *surface = meta_wayland_surface_role_get_surface (surface_role); - meta_surface_actor_wayland_add_frame_callbacks (META_SURFACE_ACTOR_WAYLAND (priv->actor), - &surface->pending_frame_callback_list); - wl_list_init (&surface->pending_frame_callback_list); + if (wl_list_empty (&surface->unassigned.pending_frame_callback_list)) + return; + + wl_list_insert_list (priv->frame_callback_list.prev, + &surface->unassigned.pending_frame_callback_list); + wl_list_init (&surface->unassigned.pending_frame_callback_list); + + meta_wayland_compositor_add_frame_callback_surface (surface->compositor, + surface); } void @@ -115,18 +121,37 @@ { MetaWaylandActorSurfacePrivate *priv = meta_wayland_actor_surface_get_instance_private (actor_surface); - MetaSurfaceActorWayland *surface_actor_wayland = - META_SURFACE_ACTOR_WAYLAND (priv->actor); + MetaWaylandSurfaceRole *surface_role = + META_WAYLAND_SURFACE_ROLE (actor_surface); + MetaWaylandSurface *surface = + meta_wayland_surface_role_get_surface (surface_role); - if (!priv->actor) + if (wl_list_empty (&pending->frame_callback_list)) return; - meta_surface_actor_wayland_add_frame_callbacks (surface_actor_wayland, - &priv->frame_callback_list); - wl_list_init (&priv->frame_callback_list); - meta_surface_actor_wayland_add_frame_callbacks (surface_actor_wayland, - &pending->frame_callback_list); + wl_list_insert_list (priv->frame_callback_list.prev, + &pending->frame_callback_list); wl_list_init (&pending->frame_callback_list); + + meta_wayland_compositor_add_frame_callback_surface (surface->compositor, + surface); +} + +void +meta_wayland_actor_surface_emit_frame_callbacks (MetaWaylandActorSurface *actor_surface, + uint32_t timestamp_ms) +{ + MetaWaylandActorSurfacePrivate *priv = + meta_wayland_actor_surface_get_instance_private (actor_surface); + + while (!wl_list_empty (&priv->frame_callback_list)) + { + MetaWaylandFrameCallback *callback = + wl_container_of (priv->frame_callback_list.next, callback, link); + + wl_callback_send_done (callback->resource, timestamp_ms); + wl_resource_destroy (callback->resource); + } } double @@ -197,7 +222,15 @@ if (!META_IS_XWAYLAND_SURFACE (surface_role)) { - if (surface->opaque_region) + if (!meta_shaped_texture_has_alpha (stex)) + { + cairo_region_t *opaque_region; + + opaque_region = cairo_region_create_rectangle (&surface_rect); + meta_surface_actor_set_opaque_region (surface_actor, opaque_region); + cairo_region_destroy (opaque_region); + } + else if (surface->opaque_region) { cairo_region_t *opaque_region; @@ -262,18 +295,17 @@ MetaWaylandActorSurfacePrivate *priv = meta_wayland_actor_surface_get_instance_private (actor_surface); - if (!priv->actor) + if (!wl_list_empty (&pending->frame_callback_list) && + priv->actor && + !meta_surface_actor_is_obscured (priv->actor)) { - wl_list_insert_list (&priv->frame_callback_list, - &pending->frame_callback_list); - wl_list_init (&pending->frame_callback_list); - return; - } + MetaWaylandSurface *surface = + meta_wayland_surface_role_get_surface (surface_role); + MetaBackend *backend = surface->compositor->backend; + ClutterActor *stage = meta_backend_get_stage (backend); - 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)); + clutter_stage_schedule_update (CLUTTER_STAGE (stage)); + } meta_wayland_actor_surface_queue_frame_callbacks (actor_surface, pending); diff -Nru mutter-3.36.1/src/wayland/meta-wayland-actor-surface.h mutter-3.36.9/src/wayland/meta-wayland-actor-surface.h --- mutter-3.36.1/src/wayland/meta-wayland-actor-surface.h 2020-03-30 19:29:39.338884000 +0000 +++ mutter-3.36.9/src/wayland/meta-wayland-actor-surface.h 2021-03-15 23:07:33.323499200 +0000 @@ -48,4 +48,7 @@ void meta_wayland_actor_surface_queue_frame_callbacks (MetaWaylandActorSurface *actor_surface, MetaWaylandSurfaceState *pending); +void meta_wayland_actor_surface_emit_frame_callbacks (MetaWaylandActorSurface *actor_surface, + uint32_t timestamp_ms); + #endif /* META_WAYLAND_ACTOR_SURFACE_H */ diff -Nru mutter-3.36.1/src/wayland/meta-wayland.c mutter-3.36.9/src/wayland/meta-wayland.c --- mutter-3.36.1/src/wayland/meta-wayland.c 2020-03-30 19:29:39.348883900 +0000 +++ mutter-3.36.9/src/wayland/meta-wayland.c 2021-03-15 23:07:33.336499000 +0000 @@ -47,7 +47,6 @@ #include "wayland/meta-xwayland-private.h" #include "wayland/meta-xwayland.h" -static MetaWaylandCompositor *_meta_wayland_compositor = NULL; static char *_display_name_override; G_DEFINE_TYPE (MetaWaylandCompositor, meta_wayland_compositor, G_TYPE_OBJECT) @@ -55,9 +54,14 @@ MetaWaylandCompositor * meta_wayland_compositor_get_default (void) { - g_assert (_meta_wayland_compositor); + MetaBackend *backend; + MetaWaylandCompositor *wayland_compositor; - return _meta_wayland_compositor; + backend = meta_get_backend (); + wayland_compositor = meta_backend_get_wayland_compositor (backend); + g_assert (wayland_compositor); + + return wayland_compositor; } typedef struct @@ -193,15 +197,35 @@ void meta_wayland_compositor_paint_finished (MetaWaylandCompositor *compositor) { - gint64 current_time = g_get_monotonic_time (); + GList *l; + int64_t now_us; + + now_us = g_get_monotonic_time (); - while (!wl_list_empty (&compositor->frame_callbacks)) + l = compositor->frame_callback_surfaces; + while (l) { - MetaWaylandFrameCallback *callback = - wl_container_of (compositor->frame_callbacks.next, callback, link); + GList *l_cur = l; + MetaWaylandSurface *surface = l->data; + MetaSurfaceActor *actor; + MetaWaylandActorSurface *actor_surface; + + l = l->next; + + actor = meta_wayland_surface_get_actor (surface); + if (!actor) + continue; + + if (!clutter_actor_has_mapped_clones (CLUTTER_ACTOR (actor)) && + meta_surface_actor_is_obscured (actor)) + continue; + + actor_surface = META_WAYLAND_ACTOR_SURFACE (surface->role); + meta_wayland_actor_surface_emit_frame_callbacks (actor_surface, + now_us / 1000); - wl_callback_send_done (callback->resource, current_time / 1000); - wl_resource_destroy (callback->resource); + compositor->frame_callback_surfaces = + g_list_delete_link (compositor->frame_callback_surfaces, l_cur); } } @@ -248,16 +272,22 @@ } void -meta_wayland_compositor_destroy_frame_callbacks (MetaWaylandCompositor *compositor, - MetaWaylandSurface *surface) +meta_wayland_compositor_add_frame_callback_surface (MetaWaylandCompositor *compositor, + MetaWaylandSurface *surface) { - MetaWaylandFrameCallback *callback, *next; + if (g_list_find (compositor->frame_callback_surfaces, surface)) + return; - wl_list_for_each_safe (callback, next, &compositor->frame_callbacks, link) - { - if (callback->surface == surface) - wl_resource_destroy (callback->resource); - } + compositor->frame_callback_surfaces = + g_list_prepend (compositor->frame_callback_surfaces, surface); +} + +void +meta_wayland_compositor_remove_frame_callback_surface (MetaWaylandCompositor *compositor, + MetaWaylandSurface *surface) +{ + compositor->frame_callback_surfaces = + g_list_remove (compositor->frame_callback_surfaces, surface); } static void @@ -309,8 +339,6 @@ static void meta_wayland_compositor_init (MetaWaylandCompositor *compositor) { - wl_list_init (&compositor->frame_callbacks); - compositor->scheduled_surface_associations = g_hash_table_new (NULL, NULL); wl_log_set_handler_server (meta_wayland_log_func); @@ -318,6 +346,8 @@ compositor->wayland_display = wl_display_create (); if (compositor->wayland_display == NULL) g_error ("Failed to create the global wl_display"); + + clutter_wayland_set_compositor_display (compositor->wayland_display); } static void @@ -325,19 +355,6 @@ { } -void -meta_wayland_pre_clutter_init (void) -{ - MetaWaylandCompositor *compositor; - - g_assert (!_meta_wayland_compositor); - - compositor = g_object_new (META_TYPE_WAYLAND_COMPOSITOR, NULL); - clutter_wayland_set_compositor_display (compositor->wayland_display); - - _meta_wayland_compositor = compositor; -} - static bool meta_xwayland_global_filter (const struct wl_client *client, const struct wl_global *global, @@ -368,8 +385,19 @@ return compositor->xwayland_manager.auth_file; } +MetaWaylandCompositor * +meta_wayland_compositor_new (MetaBackend *backend) +{ + MetaWaylandCompositor *compositor; + + compositor = g_object_new (META_TYPE_WAYLAND_COMPOSITOR, NULL); + compositor->backend = backend; + + return compositor; +} + void -meta_wayland_init (void) +meta_wayland_compositor_setup (MetaWaylandCompositor *wayland_compositor) { MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default (); GSource *wayland_event_source; @@ -395,6 +423,8 @@ meta_wayland_outputs_init (compositor); meta_wayland_data_device_manager_init (compositor); + meta_wayland_data_device_primary_manager_init (compositor); + meta_wayland_data_device_primary_legacy_manager_init (compositor); meta_wayland_subsurfaces_init (compositor); meta_wayland_shell_init (compositor); meta_wayland_pointer_gestures_init (compositor); diff -Nru mutter-3.36.1/src/wayland/meta-wayland-cursor-surface.c mutter-3.36.9/src/wayland/meta-wayland-cursor-surface.c --- mutter-3.36.1/src/wayland/meta-wayland-cursor-surface.c 2020-03-30 19:29:39.338884000 +0000 +++ mutter-3.36.9/src/wayland/meta-wayland-cursor-surface.c 2021-03-15 23:07:33.324499400 +0000 @@ -124,8 +124,8 @@ meta_wayland_cursor_surface_get_instance_private (cursor_surface); wl_list_insert_list (&priv->frame_callbacks, - &surface->pending_frame_callback_list); - wl_list_init (&surface->pending_frame_callback_list); + &surface->unassigned.pending_frame_callback_list); + wl_list_init (&surface->unassigned.pending_frame_callback_list); } static void diff -Nru mutter-3.36.1/src/wayland/meta-wayland-data-device.c mutter-3.36.9/src/wayland/meta-wayland-data-device.c --- mutter-3.36.1/src/wayland/meta-wayland-data-device.c 2020-03-30 19:29:39.339884300 +0000 +++ mutter-3.36.9/src/wayland/meta-wayland-data-device.c 2021-03-15 23:07:33.324499400 +0000 @@ -25,7 +25,6 @@ #include "config.h" #include "wayland/meta-wayland-data-device.h" -#include "wayland/meta-wayland-data-device-private.h" #include #include @@ -43,416 +42,45 @@ #include "wayland/meta-wayland-private.h" #include "wayland/meta-wayland-seat.h" -#include "gtk-primary-selection-server-protocol.h" - #define ROOTWINDOW_DROP_MIME "application/x-rootwindow-drop" -#define ALL_ACTIONS (WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY | \ - WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE | \ - WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK) - -struct _MetaWaylandDataOffer -{ - struct wl_resource *resource; - MetaWaylandDataSource *source; - struct wl_listener source_destroy_listener; - gboolean accepted; - gboolean action_sent; - uint32_t dnd_actions; - enum wl_data_device_manager_dnd_action preferred_dnd_action; - MetaSelectionType selection_type; -}; - -typedef struct _MetaWaylandDataSourcePrivate -{ - struct wl_resource *resource; - MetaWaylandDataOffer *offer; - struct wl_array mime_types; - gboolean has_target; - uint32_t dnd_actions; - enum wl_data_device_manager_dnd_action user_dnd_action; - enum wl_data_device_manager_dnd_action current_dnd_action; - MetaWaylandSeat *seat; - guint actions_set : 1; - guint in_ask : 1; - guint drop_performed : 1; -} MetaWaylandDataSourcePrivate; - -typedef struct _MetaWaylandDataSourcePrimary -{ - MetaWaylandDataSource parent; -} MetaWaylandDataSourcePrimary; - -G_DEFINE_TYPE_WITH_PRIVATE (MetaWaylandDataSource, meta_wayland_data_source, - G_TYPE_OBJECT); -G_DEFINE_TYPE (MetaWaylandDataSourcePrimary, meta_wayland_data_source_primary, - META_TYPE_WAYLAND_DATA_SOURCE); - static void unset_selection_source (MetaWaylandDataDevice *data_device, MetaSelectionType selection_type); -static MetaWaylandDataSource * -meta_wayland_data_source_new (struct wl_resource *resource); -static MetaWaylandDataSource * -meta_wayland_data_source_primary_new (struct wl_resource *resource); - -static void -meta_wayland_source_cancel (MetaWaylandDataSource *source); - static void drag_grab_data_source_destroyed (gpointer data, GObject *where_the_object_was); static struct wl_resource * create_and_send_clipboard_offer (MetaWaylandDataDevice *data_device, struct wl_resource *target); -static struct wl_resource * create_and_send_primary_offer (MetaWaylandDataDevice *data_device, - struct wl_resource *target); -static struct wl_resource * meta_wayland_data_source_get_resource (MetaWaylandDataSource *source); - -static void -unbind_resource (struct wl_resource *resource) -{ - wl_list_remove (wl_resource_get_link (resource)); -} - -static gboolean -meta_wayland_source_get_in_ask (MetaWaylandDataSource *source) -{ - MetaWaylandDataSourcePrivate *priv = - meta_wayland_data_source_get_instance_private (source); - - return priv->in_ask; -} static void -meta_wayland_source_update_in_ask (MetaWaylandDataSource *source) +move_resources (struct wl_list *destination, + struct wl_list *source) { - MetaWaylandDataSourcePrivate *priv = - meta_wayland_data_source_get_instance_private (source); - - priv->in_ask = - priv->current_dnd_action == WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK; -} - -static enum wl_data_device_manager_dnd_action -data_offer_choose_action (MetaWaylandDataOffer *offer) -{ - MetaWaylandDataSource *source = offer->source; - uint32_t actions, user_action, available_actions; - - if (wl_resource_get_version (offer->resource) < - WL_DATA_OFFER_ACTION_SINCE_VERSION) - return WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY; - - actions = meta_wayland_data_source_get_actions (source); - user_action = meta_wayland_data_source_get_user_action (source); - - available_actions = actions & offer->dnd_actions; - - if (!available_actions) - return WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE; - - /* If the user is forcing an action, go for it */ - if ((user_action & available_actions) != 0) - return user_action; - - /* If the dest side has a preferred DnD action, use it */ - if ((offer->preferred_dnd_action & available_actions) != 0) - return offer->preferred_dnd_action; - - /* Use the first found action, in bit order */ - return 1 << (ffs (available_actions) - 1); + wl_list_insert_list (destination, source); + wl_list_init (source); } static void -data_offer_update_action (MetaWaylandDataOffer *offer) +move_resources_for_client (struct wl_list *destination, + struct wl_list *source, + struct wl_client *client) { - enum wl_data_device_manager_dnd_action current_action, action; - MetaWaylandDataSource *source; - - if (!offer->source) - return; - - source = offer->source; - current_action = meta_wayland_data_source_get_current_action (source); - action = data_offer_choose_action (offer); - - if (current_action == action) - return; - - meta_wayland_data_source_set_current_action (source, action); - - if (!meta_wayland_source_get_in_ask (source) && - wl_resource_get_version (offer->resource) >= - WL_DATA_OFFER_ACTION_SINCE_VERSION) + struct wl_resource *resource, *tmp; + wl_resource_for_each_safe (resource, tmp, source) { - wl_data_offer_send_action (offer->resource, action); - offer->action_sent = TRUE; - } -} - -static struct wl_resource * -meta_wayland_data_source_get_resource (MetaWaylandDataSource *source) -{ - MetaWaylandDataSourcePrivate *priv = - meta_wayland_data_source_get_instance_private (source); - - return priv->resource; -} - -static void -meta_wayland_data_source_set_resource (MetaWaylandDataSource *source, - struct wl_resource *resource) -{ - MetaWaylandDataSourcePrivate *priv = - meta_wayland_data_source_get_instance_private (source); - - priv->resource = resource; -} - -static void -meta_wayland_data_source_target (MetaWaylandDataSource *source, - const char *mime_type) -{ - if (META_WAYLAND_DATA_SOURCE_GET_CLASS (source)->target) - META_WAYLAND_DATA_SOURCE_GET_CLASS (source)->target (source, mime_type); -} - -void -meta_wayland_data_source_send (MetaWaylandDataSource *source, - const char *mime_type, - int fd) -{ - META_WAYLAND_DATA_SOURCE_GET_CLASS (source)->send (source, mime_type, fd); -} - -gboolean -meta_wayland_data_source_has_target (MetaWaylandDataSource *source) -{ - MetaWaylandDataSourcePrivate *priv = - meta_wayland_data_source_get_instance_private (source); - - return priv->has_target; -} - -static void -meta_wayland_data_source_set_seat (MetaWaylandDataSource *source, - MetaWaylandSeat *seat) -{ - MetaWaylandDataSourcePrivate *priv = - meta_wayland_data_source_get_instance_private (source); - - priv->seat = seat; -} - -static MetaWaylandSeat * -meta_wayland_data_source_get_seat (MetaWaylandDataSource *source) -{ - MetaWaylandDataSourcePrivate *priv = - meta_wayland_data_source_get_instance_private (source); - - return priv->seat; -} - -void -meta_wayland_data_source_set_has_target (MetaWaylandDataSource *source, - gboolean has_target) -{ - MetaWaylandDataSourcePrivate *priv = - meta_wayland_data_source_get_instance_private (source); - - priv->has_target = has_target; -} - -struct wl_array * -meta_wayland_data_source_get_mime_types (const MetaWaylandDataSource *source) -{ - MetaWaylandDataSourcePrivate *priv = - meta_wayland_data_source_get_instance_private ((MetaWaylandDataSource *)source); - - return &priv->mime_types; -} - -void -meta_wayland_data_source_cancel (MetaWaylandDataSource *source) -{ - META_WAYLAND_DATA_SOURCE_GET_CLASS (source)->cancel (source); -} - -uint32_t -meta_wayland_data_source_get_actions (MetaWaylandDataSource *source) -{ - MetaWaylandDataSourcePrivate *priv = - meta_wayland_data_source_get_instance_private (source); - - return priv->dnd_actions; -} - -enum wl_data_device_manager_dnd_action -meta_wayland_data_source_get_user_action (MetaWaylandDataSource *source) -{ - MetaWaylandDataSourcePrivate *priv = - meta_wayland_data_source_get_instance_private (source); - - if (!priv->seat) - return WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE; - - return priv->user_dnd_action; -} - -enum wl_data_device_manager_dnd_action -meta_wayland_data_source_get_current_action (MetaWaylandDataSource *source) -{ - MetaWaylandDataSourcePrivate *priv = - meta_wayland_data_source_get_instance_private (source); - - return priv->current_dnd_action; -} - -static void -meta_wayland_data_source_set_current_offer (MetaWaylandDataSource *source, - MetaWaylandDataOffer *offer) -{ - MetaWaylandDataSourcePrivate *priv = - meta_wayland_data_source_get_instance_private (source); - - priv->offer = offer; -} - -static MetaWaylandDataOffer * -meta_wayland_data_source_get_current_offer (MetaWaylandDataSource *source) -{ - MetaWaylandDataSourcePrivate *priv = - meta_wayland_data_source_get_instance_private (source); - - return priv->offer; -} - -void -meta_wayland_data_source_set_current_action (MetaWaylandDataSource *source, - enum wl_data_device_manager_dnd_action action) -{ - MetaWaylandDataSourcePrivate *priv = - meta_wayland_data_source_get_instance_private (source); - - if (priv->current_dnd_action == action) - return; - - priv->current_dnd_action = action; - - if (!meta_wayland_source_get_in_ask (source)) - META_WAYLAND_DATA_SOURCE_GET_CLASS (source)->action (source, action); -} - -void -meta_wayland_data_source_set_actions (MetaWaylandDataSource *source, - uint32_t dnd_actions) -{ - MetaWaylandDataSourcePrivate *priv = - meta_wayland_data_source_get_instance_private (source); - - priv->dnd_actions = dnd_actions; - priv->actions_set = TRUE; -} - -void -meta_wayland_data_source_set_user_action (MetaWaylandDataSource *source, - uint32_t action) -{ - MetaWaylandDataSourcePrivate *priv = - meta_wayland_data_source_get_instance_private (source); - MetaWaylandDataOffer *offer; - - if (priv->user_dnd_action == action) - return; - - priv->user_dnd_action = action; - offer = meta_wayland_data_source_get_current_offer (source); - - if (offer) - data_offer_update_action (offer); -} - -static gboolean -meta_wayland_data_source_get_drop_performed (MetaWaylandDataSource *source) -{ - MetaWaylandDataSourcePrivate *priv = - meta_wayland_data_source_get_instance_private (source); - - return priv->drop_performed; -} - -static void -data_offer_accept (struct wl_client *client, - struct wl_resource *resource, - guint32 serial, - const char *mime_type) -{ - MetaWaylandDataOffer *offer = wl_resource_get_user_data (resource); - - /* FIXME: Check that client is currently focused by the input - * device that is currently dragging this data source. Should - * this be a wl_data_device request? */ - - if (offer->source) - { - meta_wayland_data_source_target (offer->source, mime_type); - meta_wayland_data_source_set_has_target (offer->source, - mime_type != NULL); - } - - offer->accepted = mime_type != NULL; -} - -static void -transfer_cb (MetaSelection *selection, - GAsyncResult *res, - GOutputStream *stream) -{ - GError *error = NULL; - - if (!meta_selection_transfer_finish (selection, res, &error)) - { - g_warning ("Could not fetch selection data: %s", error->message); - g_error_free (error); + if (wl_resource_get_client (resource) == client) + { + wl_list_remove (wl_resource_get_link (resource)); + wl_list_insert (destination, wl_resource_get_link (resource)); + } } - - g_output_stream_close (stream, NULL, NULL); } static void -data_offer_receive (struct wl_client *client, struct wl_resource *resource, - const char *mime_type, int32_t fd) +unbind_resource (struct wl_resource *resource) { - MetaWaylandDataOffer *offer = wl_resource_get_user_data (resource); - MetaDisplay *display = meta_get_display (); - MetaSelectionType selection_type; - GList *mime_types; - gboolean found; - - 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; - g_list_free_full (mime_types, g_free); - - if (found) - { - GOutputStream *stream; - - stream = g_unix_output_stream_new (fd, TRUE); - meta_selection_transfer_async (meta_display_get_selection (display), - selection_type, - mime_type, - -1, - stream, - NULL, - (GAsyncReadyCallback) transfer_cb, - stream); - } - else - { - close (fd); - } + wl_list_remove (wl_resource_get_link (resource)); } static void @@ -462,285 +90,31 @@ wl_resource_destroy (resource); } -static void -data_offer_finish (struct wl_client *client, - struct wl_resource *resource) -{ - MetaWaylandDataOffer *offer = wl_resource_get_user_data (resource); - enum wl_data_device_manager_dnd_action current_action; - - if (!offer->source || - offer != meta_wayland_data_source_get_current_offer (offer->source)) - return; - - if (!offer->accepted || !offer->action_sent) - { - wl_resource_post_error (offer->resource, - WL_DATA_OFFER_ERROR_INVALID_FINISH, - "premature finish request"); - return; - } - - current_action = meta_wayland_data_source_get_current_action (offer->source); - - if (current_action == WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE || - current_action == WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK) - { - wl_resource_post_error (offer->resource, - WL_DATA_OFFER_ERROR_INVALID_OFFER, - "offer finished with an invalid action"); - return; - } - - meta_wayland_data_source_notify_finish (offer->source); -} - -static void -data_offer_set_actions (struct wl_client *client, - struct wl_resource *resource, - uint32_t dnd_actions, - uint32_t preferred_action) -{ - MetaWaylandDataOffer *offer = wl_resource_get_user_data (resource); - - if (dnd_actions & ~(ALL_ACTIONS)) - { - wl_resource_post_error (offer->resource, - WL_DATA_OFFER_ERROR_INVALID_ACTION_MASK, - "invalid actions mask %x", dnd_actions); - return; - } - - if (preferred_action && - (!(preferred_action & dnd_actions) || - __builtin_popcount (preferred_action) > 1)) - { - wl_resource_post_error (offer->resource, - WL_DATA_OFFER_ERROR_INVALID_ACTION, - "invalid action %x", preferred_action); - return; - } - - offer->dnd_actions = dnd_actions; - offer->preferred_dnd_action = preferred_action; - - data_offer_update_action (offer); -} - -static const struct wl_data_offer_interface data_offer_interface = { - data_offer_accept, - data_offer_receive, - default_destructor, - data_offer_finish, - data_offer_set_actions, -}; - -static void -primary_offer_receive (struct wl_client *client, struct wl_resource *resource, - const char *mime_type, int32_t fd) -{ - MetaDisplay *display = meta_get_display (); - GOutputStream *stream; - GList *mime_types; - gboolean found; - - mime_types = meta_selection_get_mimetypes (meta_display_get_selection (display), - META_SELECTION_PRIMARY); - found = g_list_find_custom (mime_types, mime_type, (GCompareFunc) g_strcmp0) != NULL; - g_list_free_full (mime_types, g_free); - - if (!found) - { - close (fd); - return; - } - - stream = g_unix_output_stream_new (fd, TRUE); - meta_selection_transfer_async (meta_display_get_selection (display), - META_SELECTION_PRIMARY, - mime_type, - -1, - stream, - NULL, - (GAsyncReadyCallback) transfer_cb, - stream); -} - -static const struct gtk_primary_selection_offer_interface primary_offer_interface = { - primary_offer_receive, - default_destructor, -}; - -static void -meta_wayland_data_source_notify_drop_performed (MetaWaylandDataSource *source) -{ - META_WAYLAND_DATA_SOURCE_GET_CLASS (source)->drop_performed (source); -} - -void -meta_wayland_data_source_notify_finish (MetaWaylandDataSource *source) -{ - META_WAYLAND_DATA_SOURCE_GET_CLASS (source)->drag_finished (source); -} - -static void -destroy_data_offer (struct wl_resource *resource) -{ - MetaWaylandDataOffer *offer = wl_resource_get_user_data (resource); - MetaWaylandSeat *seat; - - if (offer->source) - { - seat = meta_wayland_data_source_get_seat (offer->source); - - if (offer == meta_wayland_data_source_get_current_offer (offer->source)) - { - if (seat->data_device.dnd_data_source == offer->source) - { - if (wl_resource_get_version (offer->resource) < - WL_DATA_OFFER_ACTION_SINCE_VERSION) - meta_wayland_data_source_notify_finish (offer->source); - else if (meta_wayland_data_source_get_drop_performed (offer->source)) - meta_wayland_source_cancel (offer->source); - } - else - { - meta_wayland_data_source_set_current_offer (offer->source, NULL); - meta_wayland_data_source_set_has_target (offer->source, FALSE); - } - } - - g_object_remove_weak_pointer (G_OBJECT (offer->source), - (gpointer *)&offer->source); - offer->source = NULL; - } - - meta_display_sync_wayland_input_focus (meta_get_display ()); - g_slice_free (MetaWaylandDataOffer, offer); -} - -static void -destroy_primary_offer (struct wl_resource *resource) -{ - MetaWaylandDataOffer *offer = wl_resource_get_user_data (resource); - - if (offer->source) - { - if (offer == meta_wayland_data_source_get_current_offer (offer->source)) - { - meta_wayland_data_source_cancel (offer->source); - meta_wayland_data_source_set_current_offer (offer->source, NULL); - } - - g_object_remove_weak_pointer (G_OBJECT (offer->source), - (gpointer *)&offer->source); - offer->source = NULL; - } - - meta_display_sync_wayland_input_focus (meta_get_display ()); - g_slice_free (MetaWaylandDataOffer, offer); -} - static struct wl_resource * create_and_send_dnd_offer (MetaWaylandDataSource *source, struct wl_resource *target) { - MetaWaylandDataSourcePrivate *priv = - meta_wayland_data_source_get_instance_private (source); - MetaWaylandDataOffer *offer = g_slice_new0 (MetaWaylandDataOffer); + MetaWaylandDataOffer *offer; + struct wl_array *mime_types; + struct wl_resource *resource; 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), - &wl_data_offer_interface, - wl_resource_get_version (target), 0); - wl_resource_set_implementation (offer->resource, - &data_offer_interface, - offer, - destroy_data_offer); - - wl_data_device_send_data_offer (target, offer->resource); - - wl_array_for_each (p, &priv->mime_types) - wl_data_offer_send_offer (offer->resource, *p); - - data_offer_update_action (offer); - meta_wayland_data_source_set_current_offer (source, offer); - - return offer->resource; -} - -static void -data_source_offer (struct wl_client *client, - struct wl_resource *resource, const char *type) -{ - MetaWaylandDataSource *source = wl_resource_get_user_data (resource); - - if (!meta_wayland_data_source_add_mime_type (source, type)) - wl_resource_post_no_memory (resource); -} - -static void -data_source_set_actions (struct wl_client *client, - struct wl_resource *resource, - uint32_t dnd_actions) -{ - MetaWaylandDataSource *source = wl_resource_get_user_data (resource); - MetaWaylandDataSourcePrivate *priv = - meta_wayland_data_source_get_instance_private (source); - - if (priv->actions_set) - { - wl_resource_post_error (priv->resource, - WL_DATA_SOURCE_ERROR_INVALID_ACTION_MASK, - "cannot set actions more than once"); - return; - } - - if (dnd_actions & ~(ALL_ACTIONS)) - { - wl_resource_post_error (priv->resource, - WL_DATA_SOURCE_ERROR_INVALID_ACTION_MASK, - "invalid actions mask %x", dnd_actions); - return; - } + offer = meta_wayland_data_offer_new (META_SELECTION_DND, source, target); + resource = meta_wayland_data_offer_get_resource (offer); - if (meta_wayland_data_source_get_seat (source)) - { - wl_resource_post_error (priv->resource, - WL_DATA_SOURCE_ERROR_INVALID_ACTION_MASK, - "invalid action change after " - "wl_data_device.start_drag"); - return; - } + wl_data_device_send_data_offer (target, resource); - meta_wayland_data_source_set_actions (source, dnd_actions); -} + mime_types = meta_wayland_data_source_get_mime_types (source); -static struct wl_data_source_interface data_source_interface = { - data_source_offer, - default_destructor, - data_source_set_actions -}; + wl_array_for_each (p, mime_types) + wl_data_offer_send_offer (resource, *p); -static void -primary_source_offer (struct wl_client *client, - struct wl_resource *resource, - const char *type) -{ - MetaWaylandDataSource *source = wl_resource_get_user_data (resource); + meta_wayland_data_offer_update_action (offer); + meta_wayland_data_source_set_current_offer (source, offer); - if (!meta_wayland_data_source_add_mime_type (source, type)) - wl_resource_post_no_memory (resource); + return resource; } -static struct gtk_primary_selection_source_interface primary_source_interface = { - primary_source_offer, - default_destructor, -}; - struct _MetaWaylandDragGrab { MetaWaylandPointerGrab generic; @@ -841,7 +215,7 @@ { uint32_t actions, user_action, action = 0; - actions = meta_wayland_data_source_get_actions (source); + meta_wayland_data_source_get_actions (source, &actions); user_action = meta_wayland_data_source_get_user_action (source); /* Pick a suitable action */ @@ -901,6 +275,12 @@ client = wl_resource_get_client (surface->resource); data_device_resource = wl_resource_find_for_client (&seat->data_device.resource_list, client); + if (!data_device_resource) + { + data_device_resource = + wl_resource_find_for_client (&seat->data_device.focus_resource_list, + client); + } if (source && data_device_resource) offer = create_and_send_dnd_offer (source, data_device_resource); @@ -972,6 +352,7 @@ static void data_device_end_drag_grab (MetaWaylandDragGrab *drag_grab) { + meta_wayland_drag_grab_set_source (drag_grab, NULL); meta_wayland_drag_grab_set_focus (drag_grab, NULL); if (drag_grab->drag_origin) @@ -986,8 +367,6 @@ wl_list_remove (&drag_grab->drag_icon_listener.link); } - meta_wayland_drag_grab_set_source (drag_grab, NULL); - if (drag_grab->feedback_actor) { clutter_actor_remove_all_children (drag_grab->feedback_actor); @@ -1068,13 +447,10 @@ meta_wayland_data_source_has_target (source) && meta_wayland_data_source_get_current_action (source)) { - /* Detach the data source from the grab, it's meant to live longer */ - meta_wayland_drag_grab_set_source (drag_grab, NULL); - meta_wayland_surface_drag_dest_drop (drag_grab->drag_focus); meta_wayland_data_source_notify_drop_performed (source); - meta_wayland_source_update_in_ask (source); + meta_wayland_data_source_update_in_ask (source); success = TRUE; } else if (!drag_grab->drag_focus && source && @@ -1121,6 +497,7 @@ drag_grab = wl_container_of (grab, drag_grab, keyboard_grab); meta_wayland_data_source_cancel (drag_grab->drag_data_source); + meta_wayland_data_source_set_current_offer (drag_grab->drag_data_source, NULL); meta_dnd_actor_drag_finish (META_DND_ACTOR (drag_grab->feedback_actor), FALSE); drag_grab->feedback_actor = NULL; data_device_end_drag_grab (drag_grab); @@ -1167,6 +544,7 @@ drag_grab->drag_origin = NULL; meta_wayland_data_device_set_dnd_source (&drag_grab->seat->data_device, NULL); unset_selection_source (&drag_grab->seat->data_device, META_SELECTION_DND); + meta_wayland_data_source_set_current_offer (drag_grab->drag_data_source, NULL); data_device_end_drag_grab (drag_grab); } @@ -1274,249 +652,79 @@ void meta_wayland_data_device_end_drag (MetaWaylandDataDevice *data_device) { - if (data_device->current_grab) - data_device_end_drag_grab (data_device->current_grab); -} - -static void -data_device_start_drag (struct wl_client *client, - struct wl_resource *resource, - struct wl_resource *source_resource, - struct wl_resource *origin_resource, - struct wl_resource *icon_resource, guint32 serial) -{ - MetaWaylandDataDevice *data_device = wl_resource_get_user_data (resource); - MetaWaylandSeat *seat = wl_container_of (data_device, seat, data_device); - MetaWaylandSurface *surface = NULL, *icon_surface = NULL; - MetaWaylandDataSource *drag_source = NULL; - MetaSelectionSource *selection_source; - - if (origin_resource) - surface = wl_resource_get_user_data (origin_resource); - - if (!surface) - return; - - if (seat->pointer->button_count == 0 || - seat->pointer->grab_serial != serial || - !seat->pointer->focus_surface || - seat->pointer->focus_surface != surface) - return; - - /* FIXME: Check that the data source type array isn't empty. */ - - if (data_device->current_grab || - seat->pointer->grab != &seat->pointer->default_grab) - return; - - if (icon_resource) - icon_surface = wl_resource_get_user_data (icon_resource); - if (source_resource) - drag_source = wl_resource_get_user_data (source_resource); - - if (icon_resource && - !meta_wayland_surface_assign_role (icon_surface, - META_TYPE_WAYLAND_SURFACE_ROLE_DND, - NULL)) - { - wl_resource_post_error (resource, WL_DATA_DEVICE_ERROR_ROLE, - "wl_surface@%d already has a different role", - wl_resource_get_id (icon_resource)); - return; - } - - 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, - &drag_grab_interface, - surface, drag_source, icon_surface); - - if (meta_wayland_seat_has_keyboard (seat)) - meta_wayland_keyboard_start_grab (seat->keyboard, - &seat->data_device.current_grab->keyboard_grab); -} - -static void -selection_data_source_destroyed (gpointer data, GObject *object_was_here) -{ - MetaWaylandDataDevice *data_device = data; - MetaWaylandSeat *seat = wl_container_of (data_device, seat, data_device); - struct wl_resource *data_device_resource; - struct wl_client *focus_client = NULL; - - data_device->selection_data_source = NULL; - - 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) - wl_data_device_send_selection (data_device_resource, NULL); - } - - unset_selection_source (data_device, META_SELECTION_CLIPBOARD); -} - -static void -meta_wayland_source_send (MetaWaylandDataSource *source, - const gchar *mime_type, - gint fd) -{ - MetaWaylandDataSourcePrivate *priv = - meta_wayland_data_source_get_instance_private (source); - - wl_data_source_send_send (priv->resource, mime_type, fd); - close (fd); -} - -static void -meta_wayland_source_target (MetaWaylandDataSource *source, - const gchar *mime_type) -{ - MetaWaylandDataSourcePrivate *priv = - meta_wayland_data_source_get_instance_private (source); - - wl_data_source_send_target (priv->resource, mime_type); -} - -static void -meta_wayland_source_cancel (MetaWaylandDataSource *source) -{ - MetaWaylandDataSourcePrivate *priv = - meta_wayland_data_source_get_instance_private (source); - - if (!priv->resource) - return; - - if (wl_resource_get_version(priv->resource) >= WL_DATA_SOURCE_DND_FINISHED_SINCE_VERSION) - wl_data_source_send_cancelled (priv->resource); -} - -static void -meta_wayland_source_action (MetaWaylandDataSource *source, - enum wl_data_device_manager_dnd_action action) -{ - MetaWaylandDataSourcePrivate *priv = - meta_wayland_data_source_get_instance_private (source); - - if (wl_resource_get_version (priv->resource) >= - WL_DATA_SOURCE_ACTION_SINCE_VERSION) - wl_data_source_send_action (priv->resource, action); -} - -static void -meta_wayland_source_drop_performed (MetaWaylandDataSource *source) -{ - MetaWaylandDataSourcePrivate *priv = - meta_wayland_data_source_get_instance_private (source); - - priv->drop_performed = TRUE; - - if (wl_resource_get_version (priv->resource) >= - WL_DATA_SOURCE_DND_DROP_PERFORMED_SINCE_VERSION) - wl_data_source_send_dnd_drop_performed (priv->resource); -} - -static void -meta_wayland_source_drag_finished (MetaWaylandDataSource *source) -{ - MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default (); - MetaWaylandDataDevice *data_device = &compositor->seat->data_device; - MetaWaylandDataSourcePrivate *priv = - meta_wayland_data_source_get_instance_private (source); - enum wl_data_device_manager_dnd_action action; - - if (meta_wayland_source_get_in_ask (source)) - { - action = meta_wayland_data_source_get_current_action (source); - meta_wayland_source_action (source, action); - } - - if (wl_resource_get_version (priv->resource) >= - WL_DATA_SOURCE_DND_FINISHED_SINCE_VERSION) - wl_data_source_send_dnd_finished (priv->resource); - - unset_selection_source (data_device, META_SELECTION_DND); -} - -static void -meta_wayland_source_finalize (GObject *object) -{ - MetaWaylandDataSource *source = META_WAYLAND_DATA_SOURCE (object); - MetaWaylandDataSourcePrivate *priv = - meta_wayland_data_source_get_instance_private (source); - char **pos; - - wl_array_for_each (pos, &priv->mime_types) - g_free (*pos); - wl_array_release (&priv->mime_types); - - G_OBJECT_CLASS (meta_wayland_data_source_parent_class)->finalize (object); + if (data_device->current_grab) + data_device_end_drag_grab (data_device->current_grab); } static void -meta_wayland_data_source_init (MetaWaylandDataSource *source) +data_device_start_drag (struct wl_client *client, + struct wl_resource *resource, + struct wl_resource *source_resource, + struct wl_resource *origin_resource, + struct wl_resource *icon_resource, guint32 serial) { - MetaWaylandDataSourcePrivate *priv = - meta_wayland_data_source_get_instance_private (source); + MetaWaylandDataDevice *data_device = wl_resource_get_user_data (resource); + MetaWaylandSeat *seat = wl_container_of (data_device, seat, data_device); + MetaWaylandSurface *surface = NULL, *icon_surface = NULL; + MetaWaylandDataSource *drag_source = NULL; + MetaSelectionSource *selection_source; - wl_array_init (&priv->mime_types); - priv->current_dnd_action = -1; - priv->drop_performed = FALSE; -} + if (origin_resource) + surface = wl_resource_get_user_data (origin_resource); -static void -meta_wayland_data_source_class_init (MetaWaylandDataSourceClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); + if (!surface) + return; - object_class->finalize = meta_wayland_source_finalize; + if (seat->pointer->button_count == 0 || + seat->pointer->grab_serial != serial || + !seat->pointer->focus_surface || + seat->pointer->focus_surface != surface) + return; - klass->send = meta_wayland_source_send; - klass->target = meta_wayland_source_target; - klass->cancel = meta_wayland_source_cancel; - klass->action = meta_wayland_source_action; - klass->drop_performed = meta_wayland_source_drop_performed; - klass->drag_finished = meta_wayland_source_drag_finished; -} + /* FIXME: Check that the data source type array isn't empty. */ -static void -meta_wayland_data_source_primary_send (MetaWaylandDataSource *source, - const gchar *mime_type, - gint fd) -{ - struct wl_resource *resource = meta_wayland_data_source_get_resource (source); + if (data_device->current_grab || + seat->pointer->grab != &seat->pointer->default_grab) + return; - gtk_primary_selection_source_send_send (resource, mime_type, fd); - close (fd); -} + if (icon_resource) + icon_surface = wl_resource_get_user_data (icon_resource); + if (source_resource) + drag_source = wl_resource_get_user_data (source_resource); -static void -meta_wayland_data_source_primary_cancel (MetaWaylandDataSource *source) -{ - struct wl_resource *resource = meta_wayland_data_source_get_resource (source); + if (icon_resource && + !meta_wayland_surface_assign_role (icon_surface, + META_TYPE_WAYLAND_SURFACE_ROLE_DND, + NULL)) + { + wl_resource_post_error (resource, WL_DATA_DEVICE_ERROR_ROLE, + "wl_surface@%d already has a different role", + wl_resource_get_id (icon_resource)); + return; + } - if (resource) - gtk_primary_selection_source_send_cancelled (resource); -} + selection_source = meta_selection_source_wayland_new (drag_source); + set_selection_source (data_device, META_SELECTION_DND, + selection_source); + g_object_unref (selection_source); -static void -meta_wayland_data_source_primary_init (MetaWaylandDataSourcePrimary *source_primary) -{ + meta_wayland_pointer_set_focus (seat->pointer, NULL); + meta_wayland_data_device_start_drag (data_device, client, + &drag_grab_interface, + surface, drag_source, icon_surface); + + if (meta_wayland_seat_has_keyboard (seat)) + meta_wayland_keyboard_start_grab (seat->keyboard, + &seat->data_device.current_grab->keyboard_grab); } static void -meta_wayland_data_source_primary_class_init (MetaWaylandDataSourcePrimaryClass *klass) +selection_data_source_destroyed (gpointer data, GObject *object_was_here) { - MetaWaylandDataSourceClass *data_source_class = - META_WAYLAND_DATA_SOURCE_CLASS (klass); + MetaWaylandDataDevice *data_device = data; - data_source_class->send = meta_wayland_data_source_primary_send; - data_source_class->cancel = meta_wayland_data_source_primary_cancel; + data_device->selection_data_source = NULL; + unset_selection_source (data_device, META_SELECTION_CLIPBOARD); } static void @@ -1525,8 +733,10 @@ MetaWaylandDataOffer *offer) { MetaWaylandDragGrab *grab = data_device->current_grab; + MetaWaylandDataSource *source; struct wl_display *display; struct wl_client *client; + struct wl_resource *resource; uint32_t source_actions; wl_fixed_t sx, sy; @@ -1540,18 +750,21 @@ wl_resource_add_destroy_listener (grab->drag_focus_data_device, &grab->drag_focus_listener); - if (wl_resource_get_version (offer->resource) >= + resource = meta_wayland_data_offer_get_resource (offer); + + if (wl_resource_get_version (resource) >= WL_DATA_OFFER_SOURCE_ACTIONS_SINCE_VERSION) { - source_actions = meta_wayland_data_source_get_actions (offer->source); - wl_data_offer_send_source_actions (offer->resource, source_actions); + source = meta_wayland_data_offer_get_source (offer); + meta_wayland_data_source_get_actions (source, &source_actions); + wl_data_offer_send_source_actions (resource, source_actions); } meta_wayland_pointer_get_relative_coordinates (grab->generic.pointer, surface, &sx, &sy); wl_data_device_send_enter (grab->drag_focus_data_device, wl_display_next_serial (display), - surface->resource, sx, sy, offer->resource); + surface->resource, sx, sy, resource); } static void @@ -1659,8 +872,6 @@ guint32 serial) { 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 && @@ -1669,7 +880,6 @@ if (data_device->selection_data_source) { - meta_wayland_data_source_cancel (data_device->selection_data_source); g_object_weak_unref (G_OBJECT (data_device->selection_data_source), selection_data_source_destroyed, data_device); @@ -1696,18 +906,6 @@ 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); - } - } } static void @@ -1718,7 +916,6 @@ { MetaWaylandDataDevice *data_device = wl_resource_get_user_data (resource); MetaWaylandSeat *seat = wl_container_of (data_device, seat, data_device); - MetaWaylandDataSourcePrivate *priv; MetaWaylandDataSource *source; if (source_resource) @@ -1728,9 +925,7 @@ if (source) { - priv = meta_wayland_data_source_get_instance_private (source); - - if (priv->actions_set) + if (meta_wayland_data_source_get_actions (source, NULL)) { wl_resource_post_error(source_resource, WL_DATA_SOURCE_ERROR_INVALID_SOURCE, @@ -1754,121 +949,6 @@ }; static void -primary_source_destroyed (gpointer data, - GObject *object_was_here) -{ - MetaWaylandDataDevice *data_device = data; - MetaWaylandSeat *seat = wl_container_of (data_device, seat, data_device); - struct wl_client *focus_client = NULL; - - data_device->primary_data_source = NULL; - - focus_client = meta_wayland_keyboard_get_focus_client (seat->keyboard); - if (focus_client) - { - struct wl_resource *data_device_resource; - - data_device_resource = wl_resource_find_for_client (&data_device->primary_resource_list, focus_client); - if (data_device_resource) - gtk_primary_selection_device_send_selection (data_device_resource, NULL); - } - - unset_selection_source (data_device, META_SELECTION_PRIMARY); -} - -void -meta_wayland_data_device_set_primary (MetaWaylandDataDevice *data_device, - MetaWaylandDataSource *source, - guint32 serial) -{ - MetaWaylandSeat *seat = wl_container_of (data_device, seat, data_device); - struct wl_resource *data_device_resource; - struct wl_client *focus_client; - MetaSelectionSource *selection_source; - - g_assert (!source || META_IS_WAYLAND_DATA_SOURCE_PRIMARY (source)); - - if (data_device->primary_data_source && - data_device->primary_serial - serial < UINT32_MAX / 2) - return; - - if (data_device->primary_data_source) - { - meta_wayland_data_source_cancel (data_device->primary_data_source); - g_object_weak_unref (G_OBJECT (data_device->primary_data_source), - primary_source_destroyed, - data_device); - } - - data_device->primary_data_source = source; - data_device->primary_serial = serial; - - if (source) - { - meta_wayland_data_source_set_seat (source, seat); - g_object_weak_ref (G_OBJECT (source), - primary_source_destroyed, - data_device); - - selection_source = meta_selection_source_wayland_new (source); - } - else - { - 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); - } - } -} - -static void -primary_device_set_selection (struct wl_client *client, - struct wl_resource *resource, - struct wl_resource *source_resource, - uint32_t serial) -{ - MetaWaylandDataDevice *data_device = wl_resource_get_user_data (resource); - MetaWaylandSeat *seat = wl_container_of (data_device, seat, data_device); - MetaWaylandDataSource *source = NULL; - - if (source_resource) - source = wl_resource_get_user_data (source_resource); - - if (wl_resource_get_client (resource) != - meta_wayland_keyboard_get_focus_client (seat->keyboard)) - return; - - meta_wayland_data_device_set_primary (data_device, source, serial); -} - -static const struct gtk_primary_selection_device_interface primary_device_interface = { - primary_device_set_selection, - default_destructor, -}; - -static void -destroy_data_source (struct wl_resource *resource) -{ - MetaWaylandDataSource *source = wl_resource_get_user_data (resource); - - meta_wayland_data_source_set_resource (source, NULL); - g_object_unref (source); -} - -static void create_data_source (struct wl_client *client, struct wl_resource *resource, guint32 id) { @@ -1894,31 +974,9 @@ if (!focus_client) return; - if (selection_type == META_SELECTION_PRIMARY) - { - data_device_resource = - wl_resource_find_for_client (&data_device->primary_resource_list, - focus_client); - if (data_device_resource) - { - struct wl_resource *offer = NULL; - - if (new_owner) - { - offer = create_and_send_primary_offer (data_device, - data_device_resource); - } - - gtk_primary_selection_device_send_selection (data_device_resource, - offer); - } - } - else if (selection_type == META_SELECTION_CLIPBOARD) + if (selection_type == META_SELECTION_CLIPBOARD) { - data_device_resource = - wl_resource_find_for_client (&data_device->resource_list, focus_client); - - if (data_device_resource) + wl_resource_for_each (data_device_resource, &data_device->focus_resource_list) { struct wl_resource *offer = NULL; @@ -1966,53 +1024,6 @@ }; static void -destroy_primary_source (struct wl_resource *resource) -{ - MetaWaylandDataSource *source = wl_resource_get_user_data (resource); - - meta_wayland_data_source_set_resource (source, NULL); - g_object_unref (source); -} - -static void -primary_device_manager_create_source (struct wl_client *client, - struct wl_resource *manager_resource, - guint32 id) -{ - struct wl_resource *source_resource; - - source_resource = - wl_resource_create (client, >k_primary_selection_source_interface, - wl_resource_get_version (manager_resource), - id); - meta_wayland_data_source_primary_new (source_resource); -} - -static void -primary_device_manager_get_device (struct wl_client *client, - struct wl_resource *manager_resource, - guint32 id, - struct wl_resource *seat_resource) -{ - MetaWaylandSeat *seat = wl_resource_get_user_data (seat_resource); - struct wl_resource *cr; - - cr = wl_resource_create (client, >k_primary_selection_device_interface, - wl_resource_get_version (manager_resource), id); - wl_resource_set_implementation (cr, &primary_device_interface, - &seat->data_device, unbind_resource); - wl_list_insert (&seat->data_device.primary_resource_list, wl_resource_get_link (cr)); - - ensure_owners_changed_handler_connected (&seat->data_device); -} - -static const struct gtk_primary_selection_device_manager_interface primary_manager_interface = { - primary_device_manager_create_source, - primary_device_manager_get_device, - default_destructor, -}; - -static void bind_manager (struct wl_client *client, void *data, guint32 version, guint32 id) { @@ -2021,19 +1032,6 @@ wl_resource_set_implementation (resource, &manager_interface, NULL, NULL); } -static void -bind_primary_manager (struct wl_client *client, - void *data, - uint32_t version, - uint32_t id) -{ - struct wl_resource *resource; - - resource = wl_resource_create (client, >k_primary_selection_device_manager_interface, - version, id); - wl_resource_set_implementation (resource, &primary_manager_interface, NULL, NULL); -} - void meta_wayland_data_device_manager_init (MetaWaylandCompositor *compositor) { @@ -2042,18 +1040,13 @@ META_WL_DATA_DEVICE_MANAGER_VERSION, NULL, bind_manager) == NULL) g_error ("Could not create data_device"); - - if (wl_global_create (compositor->wayland_display, - >k_primary_selection_device_manager_interface, - 1, NULL, bind_primary_manager) == NULL) - g_error ("Could not create data_device"); } void meta_wayland_data_device_init (MetaWaylandDataDevice *data_device) { wl_list_init (&data_device->resource_list); - wl_list_init (&data_device->primary_resource_list); + wl_list_init (&data_device->focus_resource_list); } static struct wl_resource * @@ -2062,6 +1055,7 @@ { MetaWaylandDataOffer *offer; MetaDisplay *display = meta_get_display (); + struct wl_resource *resource; GList *mimetypes, *l; mimetypes = meta_selection_get_mimetypes (meta_display_get_selection (display), @@ -2069,57 +1063,17 @@ if (!mimetypes) 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); - wl_resource_set_implementation (offer->resource, - &data_offer_interface, - offer, - destroy_data_offer); - - wl_data_device_send_data_offer (target, offer->resource); - - for (l = mimetypes; l; l = l->next) - wl_data_offer_send_offer (offer->resource, l->data); - - g_list_free_full (mimetypes, g_free); - - return offer->resource; -} - -static struct wl_resource * -create_and_send_primary_offer (MetaWaylandDataDevice *data_device, - struct wl_resource *target) -{ - MetaWaylandDataOffer *offer; - MetaDisplay *display = meta_get_display (); - GList *mimetypes, *l; - - mimetypes = meta_selection_get_mimetypes (meta_display_get_selection (display), - META_SELECTION_PRIMARY); - if (!mimetypes) - 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); - wl_resource_set_implementation (offer->resource, - &primary_offer_interface, - offer, - destroy_primary_offer); + offer = meta_wayland_data_offer_new (META_SELECTION_CLIPBOARD, NULL, target); + resource = meta_wayland_data_offer_get_resource (offer); - gtk_primary_selection_device_send_data_offer (target, offer->resource); + wl_data_device_send_data_offer (target, resource); for (l = mimetypes; l; l = l->next) - gtk_primary_selection_offer_send_offer (offer->resource, l->data); + wl_data_offer_send_offer (resource, l->data); g_list_free_full (mimetypes, g_free); - return offer->resource; + return resource; } void @@ -2135,25 +1089,23 @@ return; data_device->focus_client = focus_client; + move_resources (&data_device->resource_list, + &data_device->focus_resource_list); if (!focus_client) return; - data_device_resource = wl_resource_find_for_client (&data_device->resource_list, focus_client); - if (data_device_resource) + move_resources_for_client (&data_device->focus_resource_list, + &data_device->resource_list, + focus_client); + + wl_resource_for_each (data_device_resource, &data_device->focus_resource_list) { struct wl_resource *offer; + offer = create_and_send_clipboard_offer (data_device, data_device_resource); wl_data_device_send_selection (data_device_resource, offer); } - - 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); - } } gboolean @@ -2170,72 +1122,8 @@ return data_device->current_grab; } -gboolean -meta_wayland_data_source_has_mime_type (const MetaWaylandDataSource *source, - const gchar *mime_type) -{ - MetaWaylandDataSourcePrivate *priv = - meta_wayland_data_source_get_instance_private ((MetaWaylandDataSource *)source); - gchar **p; - - wl_array_for_each (p, &priv->mime_types) - { - if (g_strcmp0 (mime_type, *p) == 0) - return TRUE; - } - - return FALSE; -} - -static MetaWaylandDataSource * -meta_wayland_data_source_new (struct wl_resource *resource) -{ - MetaWaylandDataSource *source = - g_object_new (META_TYPE_WAYLAND_DATA_SOURCE, NULL); - MetaWaylandDataSourcePrivate *priv = - meta_wayland_data_source_get_instance_private (source); - - meta_wayland_data_source_set_resource (source, resource); - wl_resource_set_implementation (resource, &data_source_interface, - source, destroy_data_source); - - if (wl_resource_get_version (resource) < WL_DATA_SOURCE_ACTION_SINCE_VERSION) - { - priv->dnd_actions = priv->user_dnd_action = - WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY; - } - - return source; -} - -static MetaWaylandDataSource * -meta_wayland_data_source_primary_new (struct wl_resource *resource) -{ - MetaWaylandDataSource *source_primary = - g_object_new (META_TYPE_WAYLAND_DATA_SOURCE_PRIMARY, NULL); - - meta_wayland_data_source_set_resource (source_primary, resource); - wl_resource_set_implementation (resource, &primary_source_interface, - source_primary, destroy_primary_source); - - return source_primary; -} - -gboolean -meta_wayland_data_source_add_mime_type (MetaWaylandDataSource *source, - const gchar *mime_type) +void +meta_wayland_data_device_unset_dnd_selection (MetaWaylandDataDevice *data_device) { - MetaWaylandDataSourcePrivate *priv = - meta_wayland_data_source_get_instance_private (source); - gchar **pos; - - pos = wl_array_add (&priv->mime_types, sizeof (*pos)); - - if (pos) - { - *pos = g_strdup (mime_type); - return *pos != NULL; - } - - return FALSE; + unset_selection_source (data_device, META_SELECTION_DND); } diff -Nru mutter-3.36.1/src/wayland/meta-wayland-data-device.h mutter-3.36.9/src/wayland/meta-wayland-data-device.h --- mutter-3.36.1/src/wayland/meta-wayland-data-device.h 2020-03-30 19:29:39.339884300 +0000 +++ mutter-3.36.9/src/wayland/meta-wayland-data-device.h 2021-03-15 23:07:33.324499400 +0000 @@ -28,42 +28,20 @@ #include "clutter/clutter.h" #include "meta/meta-selection-source.h" +#include "wayland/meta-wayland-data-offer.h" +#include "wayland/meta-wayland-data-source.h" #include "wayland/meta-wayland-types.h" typedef struct _MetaWaylandDragGrab MetaWaylandDragGrab; typedef struct _MetaWaylandDataSourceFuncs MetaWaylandDataSourceFuncs; -#define META_TYPE_WAYLAND_DATA_SOURCE (meta_wayland_data_source_get_type ()) -G_DECLARE_DERIVABLE_TYPE (MetaWaylandDataSource, meta_wayland_data_source, - META, WAYLAND_DATA_SOURCE, GObject); - -struct _MetaWaylandDataSourceClass -{ - GObjectClass parent_class; - - void (* send) (MetaWaylandDataSource *source, - const gchar *mime_type, - gint fd); - void (* target) (MetaWaylandDataSource *source, - const gchar *mime_type); - void (* cancel) (MetaWaylandDataSource *source); - - void (* action) (MetaWaylandDataSource *source, - uint32_t action); - void (* drop_performed) (MetaWaylandDataSource *source); - void (* drag_finished) (MetaWaylandDataSource *source); -}; - struct _MetaWaylandDataDevice { uint32_t selection_serial; - uint32_t primary_serial; MetaWaylandDataSource *selection_data_source; MetaWaylandDataSource *dnd_data_source; - MetaWaylandDataSource *primary_data_source; - struct wl_listener selection_data_source_listener; struct wl_list resource_list; - struct wl_list primary_resource_list; + struct wl_list focus_resource_list; MetaWaylandDragGrab *current_grab; struct wl_client *focus_client; @@ -89,42 +67,7 @@ void meta_wayland_data_device_set_selection (MetaWaylandDataDevice *data_device, MetaWaylandDataSource *source, guint32 serial); -void meta_wayland_data_device_set_primary (MetaWaylandDataDevice *data_device, - MetaWaylandDataSource *source, - guint32 serial); - -gboolean meta_wayland_data_source_add_mime_type (MetaWaylandDataSource *source, - const gchar *mime_type); - -gboolean meta_wayland_data_source_has_mime_type (const MetaWaylandDataSource *source, - const gchar *mime_type); - -struct wl_array * - meta_wayland_data_source_get_mime_types (const MetaWaylandDataSource *source); - -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); - -void meta_wayland_data_source_notify_finish (MetaWaylandDataSource *source); - -uint32_t meta_wayland_data_source_get_actions (MetaWaylandDataSource *source); -uint32_t meta_wayland_data_source_get_user_action (MetaWaylandDataSource *source); -uint32_t meta_wayland_data_source_get_current_action (MetaWaylandDataSource *source); - -void meta_wayland_data_source_set_actions (MetaWaylandDataSource *source, - uint32_t dnd_actions); -void meta_wayland_data_source_set_user_action (MetaWaylandDataSource *source, - uint32_t action); -void meta_wayland_data_source_set_current_action (MetaWaylandDataSource *source, - uint32_t action); +void meta_wayland_data_device_unset_dnd_selection (MetaWaylandDataDevice *data_device); const MetaWaylandDragDestFuncs * meta_wayland_data_device_get_drag_dest_funcs (void); diff -Nru mutter-3.36.1/src/wayland/meta-wayland-data-device-primary.c mutter-3.36.9/src/wayland/meta-wayland-data-device-primary.c --- mutter-3.36.1/src/wayland/meta-wayland-data-device-primary.c 1970-01-01 00:00:00.000000000 +0000 +++ mutter-3.36.9/src/wayland/meta-wayland-data-device-primary.c 2021-03-15 23:07:33.324499400 +0000 @@ -0,0 +1,353 @@ +/* + * Copyright © 2011 Kristian Høgsberg + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +/* The file is based on src/data-device.c from Weston */ + +#include "config.h" + +#include "wayland/meta-wayland-data-device-primary.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-data-offer-primary.h" +#include "wayland/meta-wayland-data-source-primary.h" +#include "wayland/meta-wayland-dnd-surface.h" +#include "wayland/meta-wayland-pointer.h" +#include "wayland/meta-wayland-private.h" +#include "wayland/meta-wayland-seat.h" + +#include "primary-selection-unstable-v1-server-protocol.h" + +static struct wl_resource * create_and_send_primary_offer (MetaWaylandDataDevicePrimary *data_device, + struct wl_resource *target); + +static void +move_resources (struct wl_list *destination, + struct wl_list *source) +{ + wl_list_insert_list (destination, source); + wl_list_init (source); +} + +static void +move_resources_for_client (struct wl_list *destination, + struct wl_list *source, + struct wl_client *client) +{ + struct wl_resource *resource, *tmp; + wl_resource_for_each_safe (resource, tmp, source) + { + if (wl_resource_get_client (resource) == client) + { + wl_list_remove (wl_resource_get_link (resource)); + wl_list_insert (destination, wl_resource_get_link (resource)); + } + } +} + +static void +unbind_resource (struct wl_resource *resource) +{ + wl_list_remove (wl_resource_get_link (resource)); +} + +static void +default_destructor (struct wl_client *client, + struct wl_resource *resource) +{ + wl_resource_destroy (resource); +} + +static void +set_selection_source (MetaWaylandDataDevicePrimary *data_device, + MetaSelectionSource *selection_source) + +{ + MetaDisplay *display = meta_get_display (); + + meta_selection_set_owner (meta_display_get_selection (display), + META_SELECTION_PRIMARY, + selection_source); + g_set_object (&data_device->owner, selection_source); +} + +static void +unset_selection_source (MetaWaylandDataDevicePrimary *data_device) +{ + MetaDisplay *display = meta_get_display (); + + if (!data_device->owner) + return; + + meta_selection_unset_owner (meta_display_get_selection (display), + META_SELECTION_PRIMARY, + data_device->owner); + g_clear_object (&data_device->owner); +} + +static void +primary_source_destroyed (gpointer data, + GObject *object_was_here) +{ + MetaWaylandDataDevicePrimary *data_device = data; + + data_device->data_source = NULL; + unset_selection_source (data_device); +} + +static void +meta_wayland_data_device_primary_set_selection (MetaWaylandDataDevicePrimary *data_device, + MetaWaylandDataSource *source, + uint32_t serial) +{ + MetaWaylandSeat *seat = wl_container_of (data_device, seat, primary_data_device); + MetaSelectionSource *selection_source; + + g_assert (!source || META_IS_WAYLAND_DATA_SOURCE_PRIMARY (source)); + + if (data_device->data_source && + data_device->serial - serial < UINT32_MAX / 2) + return; + + if (data_device->data_source) + { + g_object_weak_unref (G_OBJECT (data_device->data_source), + primary_source_destroyed, + data_device); + } + + data_device->data_source = source; + data_device->serial = serial; + + if (source) + { + meta_wayland_data_source_set_seat (source, seat); + g_object_weak_ref (G_OBJECT (source), + primary_source_destroyed, + data_device); + + selection_source = meta_selection_source_wayland_new (source); + } + else + { + selection_source = g_object_new (META_TYPE_SELECTION_SOURCE_MEMORY, NULL); + } + + set_selection_source (data_device, selection_source); + g_object_unref (selection_source); +} + +static void +primary_device_set_selection (struct wl_client *client, + struct wl_resource *resource, + struct wl_resource *source_resource, + uint32_t serial) +{ + MetaWaylandDataDevicePrimary *data_device = wl_resource_get_user_data (resource); + MetaWaylandSeat *seat = wl_container_of (data_device, seat, primary_data_device); + MetaWaylandDataSource *source = NULL; + + if (source_resource) + source = wl_resource_get_user_data (source_resource); + + if (wl_resource_get_client (resource) != + meta_wayland_keyboard_get_focus_client (seat->keyboard)) + return; + + meta_wayland_data_device_primary_set_selection (data_device, source, serial); +} + +static const struct zwp_primary_selection_device_v1_interface primary_device_interface = { + primary_device_set_selection, + default_destructor, +}; + +static void +owner_changed_cb (MetaSelection *selection, + MetaSelectionType selection_type, + MetaSelectionSource *new_owner, + MetaWaylandDataDevicePrimary *data_device) +{ + MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default (); + MetaWaylandSeat *seat = compositor->seat; + struct wl_resource *data_device_resource; + struct wl_client *focus_client; + + focus_client = meta_wayland_keyboard_get_focus_client (seat->keyboard); + if (!focus_client) + return; + + if (selection_type == META_SELECTION_PRIMARY) + { + wl_resource_for_each (data_device_resource, &data_device->focus_resource_list) + { + struct wl_resource *offer = NULL; + + if (new_owner) + { + offer = create_and_send_primary_offer (data_device, + data_device_resource); + } + + zwp_primary_selection_device_v1_send_selection (data_device_resource, + offer); + } + } +} + +static void +ensure_owners_changed_handler_connected (MetaWaylandDataDevicePrimary *data_device) +{ + if (data_device->selection_owner_signal_id != 0) + return; + + data_device->selection_owner_signal_id = + g_signal_connect (meta_display_get_selection (meta_get_display ()), + "owner-changed", + G_CALLBACK (owner_changed_cb), data_device); +} + +static void +primary_device_manager_create_source (struct wl_client *client, + struct wl_resource *manager_resource, + guint32 id) +{ + struct wl_resource *source_resource; + + source_resource = + wl_resource_create (client, &zwp_primary_selection_source_v1_interface, + wl_resource_get_version (manager_resource), + id); + meta_wayland_data_source_primary_new (source_resource); +} + +static void +primary_device_manager_get_device (struct wl_client *client, + struct wl_resource *manager_resource, + guint32 id, + struct wl_resource *seat_resource) +{ + MetaWaylandSeat *seat = wl_resource_get_user_data (seat_resource); + struct wl_resource *cr; + + cr = wl_resource_create (client, &zwp_primary_selection_device_v1_interface, + wl_resource_get_version (manager_resource), id); + wl_resource_set_implementation (cr, &primary_device_interface, + &seat->primary_data_device, unbind_resource); + wl_list_insert (&seat->primary_data_device.resource_list, wl_resource_get_link (cr)); + + ensure_owners_changed_handler_connected (&seat->primary_data_device); +} + +static const struct zwp_primary_selection_device_manager_v1_interface primary_manager_interface = { + primary_device_manager_create_source, + primary_device_manager_get_device, + default_destructor, +}; + +static void +bind_primary_manager (struct wl_client *client, + void *data, + uint32_t version, + uint32_t id) +{ + struct wl_resource *resource; + + resource = wl_resource_create (client, &zwp_primary_selection_device_manager_v1_interface, + version, id); + wl_resource_set_implementation (resource, &primary_manager_interface, NULL, NULL); +} + +void +meta_wayland_data_device_primary_manager_init (MetaWaylandCompositor *compositor) +{ + if (wl_global_create (compositor->wayland_display, + &zwp_primary_selection_device_manager_v1_interface, + 1, NULL, bind_primary_manager) == NULL) + g_error ("Could not create data_device"); +} + +void +meta_wayland_data_device_primary_init (MetaWaylandDataDevicePrimary *data_device) +{ + wl_list_init (&data_device->resource_list); + wl_list_init (&data_device->focus_resource_list); +} + +static struct wl_resource * +create_and_send_primary_offer (MetaWaylandDataDevicePrimary *data_device, + struct wl_resource *target) +{ + MetaWaylandDataOffer *offer; + MetaDisplay *display = meta_get_display (); + struct wl_resource *resource; + GList *mimetypes, *l; + + mimetypes = meta_selection_get_mimetypes (meta_display_get_selection (display), + META_SELECTION_PRIMARY); + if (!mimetypes) + return NULL; + + offer = meta_wayland_data_offer_primary_new (target); + resource = meta_wayland_data_offer_get_resource (offer); + + zwp_primary_selection_device_v1_send_data_offer (target, resource); + + for (l = mimetypes; l; l = l->next) + zwp_primary_selection_offer_v1_send_offer (resource, l->data); + + g_list_free_full (mimetypes, g_free); + + return resource; +} + +void +meta_wayland_data_device_primary_set_keyboard_focus (MetaWaylandDataDevicePrimary *data_device) +{ + MetaWaylandSeat *seat = wl_container_of (data_device, seat, primary_data_device); + struct wl_client *focus_client; + struct wl_resource *data_device_resource; + + focus_client = meta_wayland_keyboard_get_focus_client (seat->keyboard); + + if (focus_client == data_device->focus_client) + return; + + data_device->focus_client = focus_client; + move_resources (&data_device->resource_list, + &data_device->focus_resource_list); + + if (!focus_client) + return; + + move_resources_for_client (&data_device->focus_resource_list, + &data_device->resource_list, + focus_client); + + wl_resource_for_each (data_device_resource, &data_device->focus_resource_list) + { + struct wl_resource *offer; + offer = create_and_send_primary_offer (data_device, data_device_resource); + zwp_primary_selection_device_v1_send_selection (data_device_resource, offer); + } +} diff -Nru mutter-3.36.1/src/wayland/meta-wayland-data-device-primary.h mutter-3.36.9/src/wayland/meta-wayland-data-device-primary.h --- mutter-3.36.1/src/wayland/meta-wayland-data-device-primary.h 1970-01-01 00:00:00.000000000 +0000 +++ mutter-3.36.9/src/wayland/meta-wayland-data-device-primary.h 2021-03-15 23:07:33.324499400 +0000 @@ -0,0 +1,55 @@ +/* + * Copyright © 2008 Kristian Høgsberg + * 2020 Red Hat Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#ifndef META_WAYLAND_DATA_DEVICE_PRIMARY_H +#define META_WAYLAND_DATA_DEVICE_PRIMARY_H + +#include +#include + +#include "clutter/clutter.h" +#include "meta/meta-selection-source.h" +#include "wayland/meta-wayland-data-offer.h" +#include "wayland/meta-wayland-data-source.h" +#include "wayland/meta-wayland-types.h" + +struct _MetaWaylandDataDevicePrimary +{ + uint32_t serial; + MetaWaylandDataSource *data_source; + struct wl_list resource_list; + struct wl_list focus_resource_list; + struct wl_client *focus_client; + + guint selection_owner_signal_id; + + MetaSelectionSource *owner; +}; + +void meta_wayland_data_device_primary_manager_init (MetaWaylandCompositor *compositor); + +void meta_wayland_data_device_primary_init (MetaWaylandDataDevicePrimary *data_device); + +void meta_wayland_data_device_primary_set_keyboard_focus (MetaWaylandDataDevicePrimary *data_device); + +#endif /* META_WAYLAND_DATA_DEVICE_PRIMARY_H */ diff -Nru mutter-3.36.1/src/wayland/meta-wayland-data-device-primary-legacy.c mutter-3.36.9/src/wayland/meta-wayland-data-device-primary-legacy.c --- mutter-3.36.1/src/wayland/meta-wayland-data-device-primary-legacy.c 1970-01-01 00:00:00.000000000 +0000 +++ mutter-3.36.9/src/wayland/meta-wayland-data-device-primary-legacy.c 2021-03-15 23:07:33.324499400 +0000 @@ -0,0 +1,354 @@ +/* + * Copyright © 2011 Kristian Høgsberg + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +/* The file is based on src/data-device.c from Weston */ + +#include "config.h" + +#include "wayland/meta-wayland-data-device-primary-legacy.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-data-offer-primary-legacy.h" +#include "wayland/meta-wayland-data-source-primary-legacy.h" +#include "wayland/meta-wayland-dnd-surface.h" +#include "wayland/meta-wayland-pointer.h" +#include "wayland/meta-wayland-private.h" +#include "wayland/meta-wayland-seat.h" + +#include "gtk-primary-selection-server-protocol.h" + +static struct wl_resource * create_and_send_primary_offer (MetaWaylandDataDevicePrimaryLegacy *data_device, + struct wl_resource *target); + +static void +move_resources (struct wl_list *destination, + struct wl_list *source) +{ + wl_list_insert_list (destination, source); + wl_list_init (source); +} + +static void +move_resources_for_client (struct wl_list *destination, + struct wl_list *source, + struct wl_client *client) +{ + struct wl_resource *resource, *tmp; + wl_resource_for_each_safe (resource, tmp, source) + { + if (wl_resource_get_client (resource) == client) + { + wl_list_remove (wl_resource_get_link (resource)); + wl_list_insert (destination, wl_resource_get_link (resource)); + } + } +} + +static void +unbind_resource (struct wl_resource *resource) +{ + wl_list_remove (wl_resource_get_link (resource)); +} + +static void +default_destructor (struct wl_client *client, + struct wl_resource *resource) +{ + wl_resource_destroy (resource); +} + +static void +set_selection_source (MetaWaylandDataDevicePrimaryLegacy *data_device, + MetaSelectionSource *selection_source) + +{ + MetaDisplay *display = meta_get_display (); + + meta_selection_set_owner (meta_display_get_selection (display), + META_SELECTION_PRIMARY, + selection_source); + g_set_object (&data_device->owner, selection_source); +} + +static void +unset_selection_source (MetaWaylandDataDevicePrimaryLegacy *data_device) +{ + MetaDisplay *display = meta_get_display (); + + if (!data_device->owner) + return; + + meta_selection_unset_owner (meta_display_get_selection (display), + META_SELECTION_PRIMARY, + data_device->owner); + g_clear_object (&data_device->owner); +} + +static void +primary_source_destroyed (gpointer data, + GObject *object_was_here) +{ + MetaWaylandDataDevicePrimaryLegacy *data_device = data; + + data_device->data_source = NULL; + unset_selection_source (data_device); +} + +static void +meta_wayland_data_device_primary_legacy_set_selection (MetaWaylandDataDevicePrimaryLegacy *data_device, + MetaWaylandDataSource *source, + uint32_t serial) +{ + MetaWaylandSeat *seat = wl_container_of (data_device, seat, primary_legacy_data_device); + MetaSelectionSource *selection_source; + + g_assert (!source || META_IS_WAYLAND_DATA_SOURCE_PRIMARY_LEGACY (source)); + + if (data_device->data_source && + data_device->serial - serial < UINT32_MAX / 2) + return; + + if (data_device->data_source) + { + g_object_weak_unref (G_OBJECT (data_device->data_source), + primary_source_destroyed, + data_device); + } + + data_device->data_source = source; + data_device->serial = serial; + + if (source) + { + meta_wayland_data_source_set_seat (source, seat); + g_object_weak_ref (G_OBJECT (source), + primary_source_destroyed, + data_device); + + selection_source = meta_selection_source_wayland_new (source); + } + else + { + selection_source = g_object_new (META_TYPE_SELECTION_SOURCE_MEMORY, NULL); + } + + set_selection_source (data_device, selection_source); + g_object_unref (selection_source); +} + +static void +primary_device_set_selection (struct wl_client *client, + struct wl_resource *resource, + struct wl_resource *source_resource, + uint32_t serial) +{ + MetaWaylandDataDevicePrimaryLegacy *data_device = wl_resource_get_user_data (resource); + MetaWaylandSeat *seat = wl_container_of (data_device, seat, primary_legacy_data_device); + MetaWaylandDataSource *source = NULL; + + if (source_resource) + source = wl_resource_get_user_data (source_resource); + + if (wl_resource_get_client (resource) != + meta_wayland_keyboard_get_focus_client (seat->keyboard)) + return; + + meta_wayland_data_device_primary_legacy_set_selection (data_device, source, serial); +} + +static const struct gtk_primary_selection_device_interface primary_device_interface = { + primary_device_set_selection, + default_destructor, +}; + +static void +owner_changed_cb (MetaSelection *selection, + MetaSelectionType selection_type, + MetaSelectionSource *new_owner, + MetaWaylandDataDevicePrimaryLegacy *data_device) +{ + MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default (); + MetaWaylandSeat *seat = compositor->seat; + struct wl_resource *data_device_resource; + struct wl_client *focus_client; + + focus_client = meta_wayland_keyboard_get_focus_client (seat->keyboard); + if (!focus_client) + return; + + if (selection_type == META_SELECTION_PRIMARY) + { + wl_resource_for_each (data_device_resource, &data_device->focus_resource_list) + { + struct wl_resource *offer = NULL; + + if (new_owner) + { + offer = create_and_send_primary_offer (data_device, + data_device_resource); + } + + gtk_primary_selection_device_send_selection (data_device_resource, + offer); + } + } +} + +static void +ensure_owners_changed_handler_connected (MetaWaylandDataDevicePrimaryLegacy *data_device) +{ + if (data_device->selection_owner_signal_id != 0) + return; + + data_device->selection_owner_signal_id = + g_signal_connect (meta_display_get_selection (meta_get_display ()), + "owner-changed", + G_CALLBACK (owner_changed_cb), data_device); +} + +static void +primary_device_manager_create_source (struct wl_client *client, + struct wl_resource *manager_resource, + guint32 id) +{ + struct wl_resource *source_resource; + + source_resource = + wl_resource_create (client, >k_primary_selection_source_interface, + wl_resource_get_version (manager_resource), + id); + meta_wayland_data_source_primary_legacy_new (source_resource); +} + +static void +primary_device_manager_get_device (struct wl_client *client, + struct wl_resource *manager_resource, + guint32 id, + struct wl_resource *seat_resource) +{ + MetaWaylandSeat *seat = wl_resource_get_user_data (seat_resource); + struct wl_resource *cr; + + cr = wl_resource_create (client, >k_primary_selection_device_interface, + wl_resource_get_version (manager_resource), id); + wl_resource_set_implementation (cr, &primary_device_interface, + &seat->primary_legacy_data_device, unbind_resource); + wl_list_insert (&seat->primary_legacy_data_device.resource_list, + wl_resource_get_link (cr)); + + ensure_owners_changed_handler_connected (&seat->primary_legacy_data_device); +} + +static const struct gtk_primary_selection_device_manager_interface primary_manager_interface = { + primary_device_manager_create_source, + primary_device_manager_get_device, + default_destructor, +}; + +static void +bind_primary_manager (struct wl_client *client, + void *data, + uint32_t version, + uint32_t id) +{ + struct wl_resource *resource; + + resource = wl_resource_create (client, >k_primary_selection_device_manager_interface, + version, id); + wl_resource_set_implementation (resource, &primary_manager_interface, NULL, NULL); +} + +void +meta_wayland_data_device_primary_legacy_manager_init (MetaWaylandCompositor *compositor) +{ + if (wl_global_create (compositor->wayland_display, + >k_primary_selection_device_manager_interface, + 1, NULL, bind_primary_manager) == NULL) + g_error ("Could not create data_device"); +} + +void +meta_wayland_data_device_primary_legacy_init (MetaWaylandDataDevicePrimaryLegacy *data_device) +{ + wl_list_init (&data_device->resource_list); + wl_list_init (&data_device->focus_resource_list); +} + +static struct wl_resource * +create_and_send_primary_offer (MetaWaylandDataDevicePrimaryLegacy *data_device, + struct wl_resource *target) +{ + MetaWaylandDataOffer *offer; + MetaDisplay *display = meta_get_display (); + struct wl_resource *resource; + GList *mimetypes, *l; + + mimetypes = meta_selection_get_mimetypes (meta_display_get_selection (display), + META_SELECTION_PRIMARY); + if (!mimetypes) + return NULL; + + offer = meta_wayland_data_offer_primary_legacy_new (target); + resource = meta_wayland_data_offer_get_resource (offer); + + gtk_primary_selection_device_send_data_offer (target, resource); + + for (l = mimetypes; l; l = l->next) + gtk_primary_selection_offer_send_offer (resource, l->data); + + g_list_free_full (mimetypes, g_free); + + return resource; +} + +void +meta_wayland_data_device_primary_legacy_set_keyboard_focus (MetaWaylandDataDevicePrimaryLegacy *data_device) +{ + MetaWaylandSeat *seat = wl_container_of (data_device, seat, primary_legacy_data_device); + struct wl_client *focus_client; + struct wl_resource *data_device_resource; + + focus_client = meta_wayland_keyboard_get_focus_client (seat->keyboard); + + if (focus_client == data_device->focus_client) + return; + + data_device->focus_client = focus_client; + move_resources (&data_device->resource_list, + &data_device->focus_resource_list); + + if (!focus_client) + return; + + move_resources_for_client (&data_device->focus_resource_list, + &data_device->resource_list, + focus_client); + + wl_resource_for_each (data_device_resource, &data_device->focus_resource_list) + { + 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); + } +} diff -Nru mutter-3.36.1/src/wayland/meta-wayland-data-device-primary-legacy.h mutter-3.36.9/src/wayland/meta-wayland-data-device-primary-legacy.h --- mutter-3.36.1/src/wayland/meta-wayland-data-device-primary-legacy.h 1970-01-01 00:00:00.000000000 +0000 +++ mutter-3.36.9/src/wayland/meta-wayland-data-device-primary-legacy.h 2021-03-15 23:07:33.324499400 +0000 @@ -0,0 +1,55 @@ +/* + * Copyright © 2008 Kristian Høgsberg + * 2020 Red Hat Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#ifndef META_WAYLAND_DATA_DEVICE_PRIMARY_LEGACY_H +#define META_WAYLAND_DATA_DEVICE_PRIMARY_LEGACY_H + +#include +#include + +#include "clutter/clutter.h" +#include "meta/meta-selection-source.h" +#include "wayland/meta-wayland-data-offer.h" +#include "wayland/meta-wayland-data-source.h" +#include "wayland/meta-wayland-types.h" + +struct _MetaWaylandDataDevicePrimaryLegacy +{ + uint32_t serial; + MetaWaylandDataSource *data_source; + struct wl_list resource_list; + struct wl_list focus_resource_list; + struct wl_client *focus_client; + + guint selection_owner_signal_id; + + MetaSelectionSource *owner; +}; + +void meta_wayland_data_device_primary_legacy_manager_init (MetaWaylandCompositor *compositor); + +void meta_wayland_data_device_primary_legacy_init (MetaWaylandDataDevicePrimaryLegacy *data_device); + +void meta_wayland_data_device_primary_legacy_set_keyboard_focus (MetaWaylandDataDevicePrimaryLegacy *data_device); + +#endif /* META_WAYLAND_DATA_DEVICE_PRIMARY_LEGACY_H */ diff -Nru mutter-3.36.1/src/wayland/meta-wayland-data-device-private.h mutter-3.36.9/src/wayland/meta-wayland-data-device-private.h --- mutter-3.36.1/src/wayland/meta-wayland-data-device-private.h 2020-03-30 19:29:39.339884300 +0000 +++ mutter-3.36.9/src/wayland/meta-wayland-data-device-private.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,34 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2015 Red Hat - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - * Written by: - * Jonas Ådahl - */ - -#ifndef META_WAYLAND_DATA_DEVICE_PRIVATE_H -#define META_WAYLAND_DATA_DEVICE_PRIVATE_H - -#define META_TYPE_WAYLAND_DATA_SOURCE_PRIMARY (meta_wayland_data_source_primary_get_type ()) -G_DECLARE_FINAL_TYPE (MetaWaylandDataSourcePrimary, - meta_wayland_data_source_primary, - META, WAYLAND_DATA_SOURCE_PRIMARY, - MetaWaylandDataSource); - -#endif /* META_WAYLAND_DATA_DEVICE_PRIVATE_H */ diff -Nru mutter-3.36.1/src/wayland/meta-wayland-data-offer.c mutter-3.36.9/src/wayland/meta-wayland-data-offer.c --- mutter-3.36.1/src/wayland/meta-wayland-data-offer.c 1970-01-01 00:00:00.000000000 +0000 +++ mutter-3.36.9/src/wayland/meta-wayland-data-offer.c 2021-03-15 23:07:33.325499300 +0000 @@ -0,0 +1,327 @@ +/* + * Copyright © 2011 Kristian Høgsberg + * 2020 Red Hat Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#include "config.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "meta/meta-selection.h" +#include "wayland/meta-wayland-data-device.h" +#include "wayland/meta-wayland-private.h" + +#include "meta-wayland-data-offer.h" + +#define ALL_ACTIONS (WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY | \ + WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE | \ + WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK) + +static void +data_offer_accept (struct wl_client *client, + struct wl_resource *resource, + guint32 serial, + const char *mime_type) +{ + MetaWaylandDataOffer *offer = wl_resource_get_user_data (resource); + + /* FIXME: Check that client is currently focused by the input + * device that is currently dragging this data source. Should + * this be a wl_data_device request? */ + + if (offer->source) + { + meta_wayland_data_source_target (offer->source, mime_type); + meta_wayland_data_source_set_has_target (offer->source, + mime_type != NULL); + } + + offer->accepted = mime_type != NULL; +} + +static void +transfer_cb (MetaSelection *selection, + GAsyncResult *res, + GOutputStream *stream) +{ + GError *error = NULL; + + if (!meta_selection_transfer_finish (selection, res, &error)) + { + g_warning ("Could not fetch selection data: %s", error->message); + g_error_free (error); + } + + g_output_stream_close (stream, NULL, NULL); + g_object_unref (stream); +} + +static void +data_offer_receive (struct wl_client *client, struct wl_resource *resource, + const char *mime_type, int32_t fd) +{ + MetaWaylandDataOffer *offer = wl_resource_get_user_data (resource); + MetaDisplay *display = meta_get_display (); + MetaSelectionType selection_type; + GList *mime_types; + gboolean found; + + 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; + g_list_free_full (mime_types, g_free); + + if (found) + { + GOutputStream *stream; + + stream = g_unix_output_stream_new (fd, TRUE); + meta_selection_transfer_async (meta_display_get_selection (display), + selection_type, + mime_type, + -1, + stream, + NULL, + (GAsyncReadyCallback) transfer_cb, + stream); + } + else + { + close (fd); + } +} + +static void +data_offer_destroy (struct wl_client *client, + struct wl_resource *resource) +{ + wl_resource_destroy (resource); +} + +static void +data_offer_finish (struct wl_client *client, + struct wl_resource *resource) +{ + MetaWaylandDataOffer *offer = wl_resource_get_user_data (resource); + enum wl_data_device_manager_dnd_action current_action; + + if (!offer->source || + offer != meta_wayland_data_source_get_current_offer (offer->source)) + return; + + if (!offer->accepted || !offer->action_sent) + { + wl_resource_post_error (offer->resource, + WL_DATA_OFFER_ERROR_INVALID_FINISH, + "premature finish request"); + return; + } + + current_action = meta_wayland_data_source_get_current_action (offer->source); + + if (current_action == WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE || + current_action == WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK) + { + wl_resource_post_error (offer->resource, + WL_DATA_OFFER_ERROR_INVALID_OFFER, + "offer finished with an invalid action"); + return; + } + + meta_wayland_data_source_notify_finish (offer->source); +} + +static void +data_offer_set_actions (struct wl_client *client, + struct wl_resource *resource, + uint32_t dnd_actions, + uint32_t preferred_action) +{ + MetaWaylandDataOffer *offer = wl_resource_get_user_data (resource); + + if (dnd_actions & ~(ALL_ACTIONS)) + { + wl_resource_post_error (offer->resource, + WL_DATA_OFFER_ERROR_INVALID_ACTION_MASK, + "invalid actions mask %x", dnd_actions); + return; + } + + if (preferred_action && + (!(preferred_action & dnd_actions) || + __builtin_popcount (preferred_action) > 1)) + { + wl_resource_post_error (offer->resource, + WL_DATA_OFFER_ERROR_INVALID_ACTION, + "invalid action %x", preferred_action); + return; + } + + offer->dnd_actions = dnd_actions; + offer->preferred_dnd_action = preferred_action; + + meta_wayland_data_offer_update_action (offer); +} + +static const struct wl_data_offer_interface data_offer_interface = { + data_offer_accept, + data_offer_receive, + data_offer_destroy, + data_offer_finish, + data_offer_set_actions, +}; + +static void +destroy_data_offer (struct wl_resource *resource) +{ + MetaWaylandDataOffer *offer = wl_resource_get_user_data (resource); + MetaWaylandSeat *seat; + + if (offer->source) + { + seat = meta_wayland_data_source_get_seat (offer->source); + + if (offer == meta_wayland_data_source_get_current_offer (offer->source)) + { + if (seat->data_device.dnd_data_source == offer->source) + { + if (wl_resource_get_version (offer->resource) < + WL_DATA_OFFER_ACTION_SINCE_VERSION) + meta_wayland_data_source_notify_finish (offer->source); + else if (meta_wayland_data_source_get_drop_performed (offer->source)) + meta_wayland_data_source_cancel (offer->source); + } + else + { + meta_wayland_data_source_set_current_offer (offer->source, NULL); + meta_wayland_data_source_set_has_target (offer->source, FALSE); + } + } + + g_object_remove_weak_pointer (G_OBJECT (offer->source), + (gpointer *)&offer->source); + offer->source = NULL; + } + + meta_display_sync_wayland_input_focus (meta_get_display ()); + g_slice_free (MetaWaylandDataOffer, offer); +} + +MetaWaylandDataOffer * +meta_wayland_data_offer_new (MetaSelectionType selection_type, + MetaWaylandDataSource *source, + struct wl_resource *target) +{ + MetaWaylandDataOffer *offer; + + offer = g_slice_new0 (MetaWaylandDataOffer); + offer->selection_type = selection_type; + offer->resource = wl_resource_create (wl_resource_get_client (target), + &wl_data_offer_interface, + wl_resource_get_version (target), 0); + wl_resource_set_implementation (offer->resource, + &data_offer_interface, + offer, + destroy_data_offer); + if (source) + { + offer->source = source; + g_object_add_weak_pointer (G_OBJECT (source), (gpointer *)&offer->source); + } + + return offer; +} + +static enum wl_data_device_manager_dnd_action +data_offer_choose_action (MetaWaylandDataOffer *offer) +{ + MetaWaylandDataSource *source = offer->source; + uint32_t actions, user_action, available_actions; + + if (wl_resource_get_version (offer->resource) < + WL_DATA_OFFER_ACTION_SINCE_VERSION) + return WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY; + + meta_wayland_data_source_get_actions (source, &actions); + user_action = meta_wayland_data_source_get_user_action (source); + + available_actions = actions & offer->dnd_actions; + + if (!available_actions) + return WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE; + + /* If the user is forcing an action, go for it */ + if ((user_action & available_actions) != 0) + return user_action; + + /* If the dest side has a preferred DnD action, use it */ + if ((offer->preferred_dnd_action & available_actions) != 0) + return offer->preferred_dnd_action; + + /* Use the first found action, in bit order */ + return 1 << (ffs (available_actions) - 1); +} + +void +meta_wayland_data_offer_update_action (MetaWaylandDataOffer *offer) +{ + enum wl_data_device_manager_dnd_action current_action, action; + MetaWaylandDataSource *source; + + if (!offer->source) + return; + + source = offer->source; + current_action = meta_wayland_data_source_get_current_action (source); + action = data_offer_choose_action (offer); + + if (current_action == action) + return; + + meta_wayland_data_source_set_current_action (source, action); + + if (!meta_wayland_data_source_get_in_ask (source) && + wl_resource_get_version (offer->resource) >= + WL_DATA_OFFER_ACTION_SINCE_VERSION) + { + wl_data_offer_send_action (offer->resource, action); + offer->action_sent = TRUE; + } +} + +struct wl_resource * +meta_wayland_data_offer_get_resource (MetaWaylandDataOffer *offer) +{ + return offer->resource; +} + +MetaWaylandDataSource * +meta_wayland_data_offer_get_source (MetaWaylandDataOffer *offer) +{ + return offer->source; +} diff -Nru mutter-3.36.1/src/wayland/meta-wayland-data-offer.h mutter-3.36.9/src/wayland/meta-wayland-data-offer.h --- mutter-3.36.1/src/wayland/meta-wayland-data-offer.h 1970-01-01 00:00:00.000000000 +0000 +++ mutter-3.36.9/src/wayland/meta-wayland-data-offer.h 2021-03-15 23:07:33.325499300 +0000 @@ -0,0 +1,51 @@ +/* + * Copyright © 2011 Kristian Høgsberg + * 2020 Red Hat Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#ifndef META_WAYLAND_DATA_OFFER_H +#define META_WAYLAND_DATA_OFFER_H + +#include "meta/meta-selection.h" +#include "wayland/meta-wayland-data-source.h" + +struct _MetaWaylandDataOffer +{ + struct wl_resource *resource; + MetaWaylandDataSource *source; + struct wl_listener source_destroy_listener; + gboolean accepted; + gboolean action_sent; + uint32_t dnd_actions; + enum wl_data_device_manager_dnd_action preferred_dnd_action; + MetaSelectionType selection_type; +}; + +MetaWaylandDataOffer * meta_wayland_data_offer_new (MetaSelectionType selection_type, + MetaWaylandDataSource *source, + struct wl_resource *resource); + +void meta_wayland_data_offer_update_action (MetaWaylandDataOffer *offer); + +struct wl_resource * meta_wayland_data_offer_get_resource (MetaWaylandDataOffer *offer); +MetaWaylandDataSource * meta_wayland_data_offer_get_source (MetaWaylandDataOffer *offer); + +#endif /* META_WAYLAND_DATA_OFFER_H */ diff -Nru mutter-3.36.1/src/wayland/meta-wayland-data-offer-primary.c mutter-3.36.9/src/wayland/meta-wayland-data-offer-primary.c --- mutter-3.36.1/src/wayland/meta-wayland-data-offer-primary.c 1970-01-01 00:00:00.000000000 +0000 +++ mutter-3.36.9/src/wayland/meta-wayland-data-offer-primary.c 2021-03-15 23:07:33.325499300 +0000 @@ -0,0 +1,139 @@ +/* + * Copyright © 2011 Kristian Høgsberg + * 2020 Red Hat Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#include "config.h" + +#include "meta-wayland-data-offer-primary.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "core/display-private.h" +#include "primary-selection-unstable-v1-server-protocol.h" +#include "wayland/meta-wayland-data-offer.h" + +static void +transfer_cb (MetaSelection *selection, + GAsyncResult *res, + GOutputStream *stream) +{ + GError *error = NULL; + + if (!meta_selection_transfer_finish (selection, res, &error)) + { + g_warning ("Could not fetch selection data: %s", error->message); + g_error_free (error); + } + + g_output_stream_close (stream, NULL, NULL); + g_object_unref (stream); +} + +static void +primary_offer_receive (struct wl_client *client, + struct wl_resource *resource, + const char *mime_type, + int32_t fd) +{ + MetaDisplay *display = meta_get_display (); + GOutputStream *stream; + GList *mime_types; + gboolean found; + + mime_types = meta_selection_get_mimetypes (meta_display_get_selection (display), + META_SELECTION_PRIMARY); + found = g_list_find_custom (mime_types, mime_type, (GCompareFunc) g_strcmp0) != NULL; + g_list_free_full (mime_types, g_free); + + if (!found) + { + close (fd); + return; + } + + stream = g_unix_output_stream_new (fd, TRUE); + meta_selection_transfer_async (meta_display_get_selection (display), + META_SELECTION_PRIMARY, + mime_type, + -1, + stream, + NULL, + (GAsyncReadyCallback) transfer_cb, + stream); +} + +static void +primary_offer_destroy (struct wl_client *client, + struct wl_resource *resource) +{ + wl_resource_destroy (resource); +} + +static const struct zwp_primary_selection_offer_v1_interface primary_offer_interface = { + primary_offer_receive, + primary_offer_destroy, +}; + +static void +destroy_primary_offer (struct wl_resource *resource) +{ + MetaWaylandDataOffer *offer = wl_resource_get_user_data (resource); + + if (offer->source) + { + if (offer == meta_wayland_data_source_get_current_offer (offer->source)) + { + meta_wayland_data_source_cancel (offer->source); + meta_wayland_data_source_set_current_offer (offer->source, NULL); + } + + g_object_remove_weak_pointer (G_OBJECT (offer->source), + (gpointer *)&offer->source); + offer->source = NULL; + } + + meta_display_sync_wayland_input_focus (meta_get_display ()); + g_slice_free (MetaWaylandDataOffer, offer); +} + +MetaWaylandDataOffer * +meta_wayland_data_offer_primary_new (struct wl_resource *target) +{ + MetaWaylandDataOffer *offer; + + offer = g_slice_new0 (MetaWaylandDataOffer); + offer->selection_type = META_SELECTION_PRIMARY; + offer->resource = wl_resource_create (wl_resource_get_client (target), + &zwp_primary_selection_offer_v1_interface, + wl_resource_get_version (target), 0); + wl_resource_set_implementation (offer->resource, + &primary_offer_interface, + offer, + destroy_primary_offer); + return offer; +} diff -Nru mutter-3.36.1/src/wayland/meta-wayland-data-offer-primary.h mutter-3.36.9/src/wayland/meta-wayland-data-offer-primary.h --- mutter-3.36.1/src/wayland/meta-wayland-data-offer-primary.h 1970-01-01 00:00:00.000000000 +0000 +++ mutter-3.36.9/src/wayland/meta-wayland-data-offer-primary.h 2021-03-15 23:07:33.325499300 +0000 @@ -0,0 +1,31 @@ +/* + * Copyright © 2011 Kristian Høgsberg + * 2020 Red Hat Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#ifndef META_WAYLAND_DATA_OFFER_PRIMARY_H +#define META_WAYLAND_DATA_OFFER_PRIMARY_H + +#include "meta-wayland-data-offer.h" + +MetaWaylandDataOffer * meta_wayland_data_offer_primary_new (struct wl_resource *target); + +#endif /* META_WAYLAND_DATA_OFFER_PRIMARY_H */ diff -Nru mutter-3.36.1/src/wayland/meta-wayland-data-offer-primary-legacy.c mutter-3.36.9/src/wayland/meta-wayland-data-offer-primary-legacy.c --- mutter-3.36.1/src/wayland/meta-wayland-data-offer-primary-legacy.c 1970-01-01 00:00:00.000000000 +0000 +++ mutter-3.36.9/src/wayland/meta-wayland-data-offer-primary-legacy.c 2021-03-15 23:07:33.325499300 +0000 @@ -0,0 +1,139 @@ +/* + * Copyright © 2011 Kristian Høgsberg + * 2020 Red Hat Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#include "config.h" + +#include "meta-wayland-data-offer-primary-legacy.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "core/display-private.h" +#include "gtk-primary-selection-server-protocol.h" +#include "wayland/meta-wayland-data-offer.h" + +static void +transfer_cb (MetaSelection *selection, + GAsyncResult *res, + GOutputStream *stream) +{ + GError *error = NULL; + + if (!meta_selection_transfer_finish (selection, res, &error)) + { + g_warning ("Could not fetch selection data: %s", error->message); + g_error_free (error); + } + + g_output_stream_close (stream, NULL, NULL); + g_object_unref (stream); +} + +static void +primary_offer_receive (struct wl_client *client, + struct wl_resource *resource, + const char *mime_type, + int32_t fd) +{ + MetaDisplay *display = meta_get_display (); + GOutputStream *stream; + GList *mime_types; + gboolean found; + + mime_types = meta_selection_get_mimetypes (meta_display_get_selection (display), + META_SELECTION_PRIMARY); + found = g_list_find_custom (mime_types, mime_type, (GCompareFunc) g_strcmp0) != NULL; + g_list_free_full (mime_types, g_free); + + if (!found) + { + close (fd); + return; + } + + stream = g_unix_output_stream_new (fd, TRUE); + meta_selection_transfer_async (meta_display_get_selection (display), + META_SELECTION_PRIMARY, + mime_type, + -1, + stream, + NULL, + (GAsyncReadyCallback) transfer_cb, + stream); +} + +static void +primary_offer_destroy (struct wl_client *client, + struct wl_resource *resource) +{ + wl_resource_destroy (resource); +} + +static const struct gtk_primary_selection_offer_interface primary_offer_interface = { + primary_offer_receive, + primary_offer_destroy, +}; + +static void +destroy_primary_offer (struct wl_resource *resource) +{ + MetaWaylandDataOffer *offer = wl_resource_get_user_data (resource); + + if (offer->source) + { + if (offer == meta_wayland_data_source_get_current_offer (offer->source)) + { + meta_wayland_data_source_cancel (offer->source); + meta_wayland_data_source_set_current_offer (offer->source, NULL); + } + + g_object_remove_weak_pointer (G_OBJECT (offer->source), + (gpointer *)&offer->source); + offer->source = NULL; + } + + meta_display_sync_wayland_input_focus (meta_get_display ()); + g_slice_free (MetaWaylandDataOffer, offer); +} + +MetaWaylandDataOffer * +meta_wayland_data_offer_primary_legacy_new (struct wl_resource *target) +{ + MetaWaylandDataOffer *offer; + + 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); + wl_resource_set_implementation (offer->resource, + &primary_offer_interface, + offer, + destroy_primary_offer); + return offer; +} diff -Nru mutter-3.36.1/src/wayland/meta-wayland-data-offer-primary-legacy.h mutter-3.36.9/src/wayland/meta-wayland-data-offer-primary-legacy.h --- mutter-3.36.1/src/wayland/meta-wayland-data-offer-primary-legacy.h 1970-01-01 00:00:00.000000000 +0000 +++ mutter-3.36.9/src/wayland/meta-wayland-data-offer-primary-legacy.h 2021-03-15 23:07:33.325499300 +0000 @@ -0,0 +1,31 @@ +/* + * Copyright © 2011 Kristian Høgsberg + * 2020 Red Hat Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#ifndef META_WAYLAND_DATA_OFFER_PRIMARY_LEGACY_H +#define META_WAYLAND_DATA_OFFER_PRIMARY_LEGACY_H + +#include "meta-wayland-data-offer.h" + +MetaWaylandDataOffer * meta_wayland_data_offer_primary_legacy_new (struct wl_resource *target); + +#endif /* META_WAYLAND_DATA_OFFER_PRIMARY_LEGACY_H */ diff -Nru mutter-3.36.1/src/wayland/meta-wayland-data-source.c mutter-3.36.9/src/wayland/meta-wayland-data-source.c --- mutter-3.36.1/src/wayland/meta-wayland-data-source.c 1970-01-01 00:00:00.000000000 +0000 +++ mutter-3.36.9/src/wayland/meta-wayland-data-source.c 2021-03-15 23:07:33.325499300 +0000 @@ -0,0 +1,523 @@ +/* + * Copyright © 2011 Kristian Høgsberg + * 2020 Red Hat Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#include "config.h" + +#include + +#include "wayland/meta-wayland-data-source.h" +#include "wayland/meta-wayland-private.h" + +#define ALL_ACTIONS (WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY | \ + WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE | \ + WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK) + +typedef struct _MetaWaylandDataSourcePrivate +{ + struct wl_resource *resource; + MetaWaylandDataOffer *offer; + struct wl_array mime_types; + gboolean has_target; + uint32_t dnd_actions; + enum wl_data_device_manager_dnd_action user_dnd_action; + enum wl_data_device_manager_dnd_action current_dnd_action; + MetaWaylandSeat *seat; + guint actions_set : 1; + guint in_ask : 1; + guint drop_performed : 1; +} MetaWaylandDataSourcePrivate; + +G_DEFINE_TYPE_WITH_PRIVATE (MetaWaylandDataSource, meta_wayland_data_source, + G_TYPE_OBJECT); + +static void +meta_wayland_data_source_real_send (MetaWaylandDataSource *source, + const gchar *mime_type, + gint fd) +{ + MetaWaylandDataSourcePrivate *priv = + meta_wayland_data_source_get_instance_private (source); + + wl_data_source_send_send (priv->resource, mime_type, fd); + close (fd); +} + +static void +meta_wayland_data_source_real_target (MetaWaylandDataSource *source, + const gchar *mime_type) +{ + MetaWaylandDataSourcePrivate *priv = + meta_wayland_data_source_get_instance_private (source); + + wl_data_source_send_target (priv->resource, mime_type); +} + +static void +meta_wayland_data_source_real_cancel (MetaWaylandDataSource *source) +{ + MetaWaylandDataSourcePrivate *priv = + meta_wayland_data_source_get_instance_private (source); + + if (!priv->resource) + return; + + wl_data_source_send_cancelled (priv->resource); +} + +static void +meta_wayland_data_source_real_action (MetaWaylandDataSource *source, + enum wl_data_device_manager_dnd_action action) +{ + MetaWaylandDataSourcePrivate *priv = + meta_wayland_data_source_get_instance_private (source); + + if (wl_resource_get_version (priv->resource) >= + WL_DATA_SOURCE_ACTION_SINCE_VERSION) + wl_data_source_send_action (priv->resource, action); +} + +static void +meta_wayland_data_source_real_drop_performed (MetaWaylandDataSource *source) +{ + MetaWaylandDataSourcePrivate *priv = + meta_wayland_data_source_get_instance_private (source); + + if (wl_resource_get_version (priv->resource) >= + WL_DATA_SOURCE_DND_DROP_PERFORMED_SINCE_VERSION) + { + priv->drop_performed = TRUE; + wl_data_source_send_dnd_drop_performed (priv->resource); + } +} + +static void +meta_wayland_data_source_real_drag_finished (MetaWaylandDataSource *source) +{ + MetaWaylandDataSourcePrivate *priv = + meta_wayland_data_source_get_instance_private (source); + enum wl_data_device_manager_dnd_action action; + + if (meta_wayland_data_source_get_in_ask (source)) + { + action = meta_wayland_data_source_get_current_action (source); + meta_wayland_data_source_real_action (source, action); + } + + if (wl_resource_get_version (priv->resource) >= + WL_DATA_SOURCE_DND_FINISHED_SINCE_VERSION) + wl_data_source_send_dnd_finished (priv->resource); +} + +static void +meta_wayland_data_source_finalize (GObject *object) +{ + MetaWaylandDataSource *source = META_WAYLAND_DATA_SOURCE (object); + MetaWaylandDataSourcePrivate *priv = + meta_wayland_data_source_get_instance_private (source); + char **pos; + + wl_array_for_each (pos, &priv->mime_types) + g_free (*pos); + wl_array_release (&priv->mime_types); + + G_OBJECT_CLASS (meta_wayland_data_source_parent_class)->finalize (object); +} + +static void +meta_wayland_data_source_init (MetaWaylandDataSource *source) +{ + MetaWaylandDataSourcePrivate *priv = + meta_wayland_data_source_get_instance_private (source); + + wl_array_init (&priv->mime_types); + priv->current_dnd_action = -1; + priv->drop_performed = FALSE; +} + +static void +meta_wayland_data_source_class_init (MetaWaylandDataSourceClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->finalize = meta_wayland_data_source_finalize; + + klass->send = meta_wayland_data_source_real_send; + klass->target = meta_wayland_data_source_real_target; + klass->cancel = meta_wayland_data_source_real_cancel; + klass->action = meta_wayland_data_source_real_action; + klass->drop_performed = meta_wayland_data_source_real_drop_performed; + klass->drag_finished = meta_wayland_data_source_real_drag_finished; +} + + +static void +data_source_offer (struct wl_client *client, + struct wl_resource *resource, const char *type) +{ + MetaWaylandDataSource *source = wl_resource_get_user_data (resource); + + if (!meta_wayland_data_source_add_mime_type (source, type)) + wl_resource_post_no_memory (resource); +} + +static void +data_source_destroy (struct wl_client *client, + struct wl_resource *resource) +{ + wl_resource_destroy (resource); +} + +static void +data_source_set_actions (struct wl_client *client, + struct wl_resource *resource, + uint32_t dnd_actions) +{ + MetaWaylandDataSource *source = wl_resource_get_user_data (resource); + MetaWaylandDataSourcePrivate *priv = + meta_wayland_data_source_get_instance_private (source); + + if (priv->actions_set) + { + wl_resource_post_error (priv->resource, + WL_DATA_SOURCE_ERROR_INVALID_ACTION_MASK, + "cannot set actions more than once"); + return; + } + + if (dnd_actions & ~(ALL_ACTIONS)) + { + wl_resource_post_error (priv->resource, + WL_DATA_SOURCE_ERROR_INVALID_ACTION_MASK, + "invalid actions mask %x", dnd_actions); + return; + } + + if (meta_wayland_data_source_get_seat (source)) + { + wl_resource_post_error (priv->resource, + WL_DATA_SOURCE_ERROR_INVALID_ACTION_MASK, + "invalid action change after " + "wl_data_device.start_drag"); + return; + } + + meta_wayland_data_source_set_actions (source, dnd_actions); +} + +static struct wl_data_source_interface data_source_interface = { + data_source_offer, + data_source_destroy, + data_source_set_actions +}; + +static void +destroy_data_source (struct wl_resource *resource) +{ + MetaWaylandDataSource *source = wl_resource_get_user_data (resource); + + meta_wayland_data_source_set_resource (source, NULL); + g_object_unref (source); +} + +MetaWaylandDataSource * +meta_wayland_data_source_new (struct wl_resource *resource) +{ + MetaWaylandDataSource *source = + g_object_new (META_TYPE_WAYLAND_DATA_SOURCE, NULL); + MetaWaylandDataSourcePrivate *priv = + meta_wayland_data_source_get_instance_private (source); + + meta_wayland_data_source_set_resource (source, resource); + wl_resource_set_implementation (resource, &data_source_interface, + source, destroy_data_source); + + if (wl_resource_get_version (resource) < WL_DATA_SOURCE_ACTION_SINCE_VERSION) + { + priv->dnd_actions = priv->user_dnd_action = + WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY; + } + + return source; +} + +struct wl_resource * +meta_wayland_data_source_get_resource (MetaWaylandDataSource *source) +{ + MetaWaylandDataSourcePrivate *priv = + meta_wayland_data_source_get_instance_private (source); + + return priv->resource; +} + +void +meta_wayland_data_source_set_resource (MetaWaylandDataSource *source, + struct wl_resource *resource) +{ + MetaWaylandDataSourcePrivate *priv = + meta_wayland_data_source_get_instance_private (source); + + priv->resource = resource; +} + +gboolean +meta_wayland_data_source_get_in_ask (MetaWaylandDataSource *source) +{ + MetaWaylandDataSourcePrivate *priv = + meta_wayland_data_source_get_instance_private (source); + + return priv->in_ask; +} + +void +meta_wayland_data_source_update_in_ask (MetaWaylandDataSource *source) +{ + MetaWaylandDataSourcePrivate *priv = + meta_wayland_data_source_get_instance_private (source); + + priv->in_ask = + priv->current_dnd_action == WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK; +} + +void +meta_wayland_data_source_target (MetaWaylandDataSource *source, + const char *mime_type) +{ + if (META_WAYLAND_DATA_SOURCE_GET_CLASS (source)->target) + META_WAYLAND_DATA_SOURCE_GET_CLASS (source)->target (source, mime_type); +} + +void +meta_wayland_data_source_send (MetaWaylandDataSource *source, + const char *mime_type, + int fd) +{ + META_WAYLAND_DATA_SOURCE_GET_CLASS (source)->send (source, mime_type, fd); +} + +gboolean +meta_wayland_data_source_has_target (MetaWaylandDataSource *source) +{ + MetaWaylandDataSourcePrivate *priv = + meta_wayland_data_source_get_instance_private (source); + + return priv->has_target; +} + +void +meta_wayland_data_source_set_seat (MetaWaylandDataSource *source, + MetaWaylandSeat *seat) +{ + MetaWaylandDataSourcePrivate *priv = + meta_wayland_data_source_get_instance_private (source); + + priv->seat = seat; +} + +MetaWaylandSeat * +meta_wayland_data_source_get_seat (MetaWaylandDataSource *source) +{ + MetaWaylandDataSourcePrivate *priv = + meta_wayland_data_source_get_instance_private (source); + + return priv->seat; +} + +void +meta_wayland_data_source_set_has_target (MetaWaylandDataSource *source, + gboolean has_target) +{ + MetaWaylandDataSourcePrivate *priv = + meta_wayland_data_source_get_instance_private (source); + + priv->has_target = has_target; +} + +struct wl_array * +meta_wayland_data_source_get_mime_types (MetaWaylandDataSource *source) +{ + MetaWaylandDataSourcePrivate *priv = + meta_wayland_data_source_get_instance_private ((MetaWaylandDataSource *)source); + + return &priv->mime_types; +} + +void +meta_wayland_data_source_cancel (MetaWaylandDataSource *source) +{ + META_WAYLAND_DATA_SOURCE_GET_CLASS (source)->cancel (source); +} + +gboolean +meta_wayland_data_source_get_actions (MetaWaylandDataSource *source, + uint32_t *dnd_actions) +{ + MetaWaylandDataSourcePrivate *priv = + meta_wayland_data_source_get_instance_private (source); + + if (dnd_actions) + *dnd_actions = priv->dnd_actions; + + return priv->actions_set; +} + +enum wl_data_device_manager_dnd_action +meta_wayland_data_source_get_user_action (MetaWaylandDataSource *source) +{ + MetaWaylandDataSourcePrivate *priv = + meta_wayland_data_source_get_instance_private (source); + + if (!priv->seat) + return WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE; + + return priv->user_dnd_action; +} + +enum wl_data_device_manager_dnd_action +meta_wayland_data_source_get_current_action (MetaWaylandDataSource *source) +{ + MetaWaylandDataSourcePrivate *priv = + meta_wayland_data_source_get_instance_private (source); + + return priv->current_dnd_action; +} + +void +meta_wayland_data_source_set_current_offer (MetaWaylandDataSource *source, + MetaWaylandDataOffer *offer) +{ + MetaWaylandDataSourcePrivate *priv = + meta_wayland_data_source_get_instance_private (source); + + priv->offer = offer; +} + +MetaWaylandDataOffer * +meta_wayland_data_source_get_current_offer (MetaWaylandDataSource *source) +{ + MetaWaylandDataSourcePrivate *priv = + meta_wayland_data_source_get_instance_private (source); + + return priv->offer; +} + +void +meta_wayland_data_source_set_current_action (MetaWaylandDataSource *source, + enum wl_data_device_manager_dnd_action action) +{ + MetaWaylandDataSourcePrivate *priv = + meta_wayland_data_source_get_instance_private (source); + + if (priv->current_dnd_action == action) + return; + + priv->current_dnd_action = action; + + if (!meta_wayland_data_source_get_in_ask (source)) + META_WAYLAND_DATA_SOURCE_GET_CLASS (source)->action (source, action); +} + +void +meta_wayland_data_source_set_actions (MetaWaylandDataSource *source, + uint32_t dnd_actions) +{ + MetaWaylandDataSourcePrivate *priv = + meta_wayland_data_source_get_instance_private (source); + + priv->dnd_actions = dnd_actions; + priv->actions_set = TRUE; +} + +void +meta_wayland_data_source_set_user_action (MetaWaylandDataSource *source, + uint32_t action) +{ + MetaWaylandDataSourcePrivate *priv = + meta_wayland_data_source_get_instance_private (source); + MetaWaylandDataOffer *offer; + + if (priv->user_dnd_action == action) + return; + + priv->user_dnd_action = action; + offer = meta_wayland_data_source_get_current_offer (source); + + if (offer) + meta_wayland_data_offer_update_action (offer); +} + +gboolean +meta_wayland_data_source_get_drop_performed (MetaWaylandDataSource *source) +{ + MetaWaylandDataSourcePrivate *priv = + meta_wayland_data_source_get_instance_private (source); + + return priv->drop_performed; +} + +void +meta_wayland_data_source_notify_drop_performed (MetaWaylandDataSource *source) +{ + META_WAYLAND_DATA_SOURCE_GET_CLASS (source)->drop_performed (source); +} + +void +meta_wayland_data_source_notify_finish (MetaWaylandDataSource *source) +{ + META_WAYLAND_DATA_SOURCE_GET_CLASS (source)->drag_finished (source); +} + +gboolean +meta_wayland_data_source_add_mime_type (MetaWaylandDataSource *source, + const char *mime_type) +{ + MetaWaylandDataSourcePrivate *priv = + meta_wayland_data_source_get_instance_private (source); + char **pos; + + pos = wl_array_add (&priv->mime_types, sizeof (*pos)); + + if (pos) + { + *pos = g_strdup (mime_type); + return *pos != NULL; + } + + return FALSE; +} + +gboolean +meta_wayland_data_source_has_mime_type (MetaWaylandDataSource *source, + const char *mime_type) +{ + MetaWaylandDataSourcePrivate *priv = + meta_wayland_data_source_get_instance_private (source); + char **p; + + wl_array_for_each (p, &priv->mime_types) + { + if (g_strcmp0 (mime_type, *p) == 0) + return TRUE; + } + + return FALSE; +} diff -Nru mutter-3.36.1/src/wayland/meta-wayland-data-source.h mutter-3.36.9/src/wayland/meta-wayland-data-source.h --- mutter-3.36.1/src/wayland/meta-wayland-data-source.h 1970-01-01 00:00:00.000000000 +0000 +++ mutter-3.36.9/src/wayland/meta-wayland-data-source.h 2021-03-15 23:07:33.325499300 +0000 @@ -0,0 +1,112 @@ +/* + * Copyright © 2011 Kristian Høgsberg + * 2020 Red Hat Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#ifndef META_WAYLAND_DATA_SOURCE_H +#define META_WAYLAND_DATA_SOURCE_H + +#include +#include + +#include "wayland/meta-wayland-types.h" + +#define META_TYPE_WAYLAND_DATA_SOURCE (meta_wayland_data_source_get_type ()) +G_DECLARE_DERIVABLE_TYPE (MetaWaylandDataSource, + meta_wayland_data_source, + META, WAYLAND_DATA_SOURCE, + GObject) + +typedef struct _MetaWaylandDataSourceClass MetaWaylandDataSourceClass; + +struct _MetaWaylandDataSourceClass +{ + GObjectClass parent_class; + + void (* send) (MetaWaylandDataSource *source, + const gchar *mime_type, + gint fd); + void (* target) (MetaWaylandDataSource *source, + const gchar *mime_type); + void (* cancel) (MetaWaylandDataSource *source); + + void (* action) (MetaWaylandDataSource *source, + uint32_t action); + void (* drop_performed) (MetaWaylandDataSource *source); + void (* drag_finished) (MetaWaylandDataSource *source); +}; + +MetaWaylandDataSource * meta_wayland_data_source_new (struct wl_resource *resource); + +struct wl_resource * meta_wayland_data_source_get_resource (MetaWaylandDataSource *source); +void meta_wayland_data_source_set_resource (MetaWaylandDataSource *source, + struct wl_resource *resource); + +gboolean meta_wayland_data_source_get_in_ask (MetaWaylandDataSource *source); +void meta_wayland_data_source_update_in_ask (MetaWaylandDataSource *source); + +void meta_wayland_data_source_target (MetaWaylandDataSource *source, + const char *mime_type); +void meta_wayland_data_source_send (MetaWaylandDataSource *source, + const char *mime_type, + int fd); +void meta_wayland_data_source_cancel (MetaWaylandDataSource *source); + +gboolean meta_wayland_data_source_has_target (MetaWaylandDataSource *source); + +void meta_wayland_data_source_set_seat (MetaWaylandDataSource *source, + MetaWaylandSeat *seat); +MetaWaylandSeat * meta_wayland_data_source_get_seat (MetaWaylandDataSource *source); + +void meta_wayland_data_source_set_has_target (MetaWaylandDataSource *source, + gboolean has_target); +struct wl_array * meta_wayland_data_source_get_mime_types (MetaWaylandDataSource *source); +gboolean meta_wayland_data_source_add_mime_type (MetaWaylandDataSource *source, + const gchar *mime_type); +gboolean meta_wayland_data_source_has_mime_type (MetaWaylandDataSource *source, + const char *mime_type); + +gboolean meta_wayland_data_source_get_actions (MetaWaylandDataSource *source, + uint32_t *dnd_actions); +void meta_wayland_data_source_set_actions (MetaWaylandDataSource *source, + uint32_t dnd_actions); + +enum wl_data_device_manager_dnd_action + meta_wayland_data_source_get_current_action (MetaWaylandDataSource *source); +void meta_wayland_data_source_set_current_action (MetaWaylandDataSource *source, + enum wl_data_device_manager_dnd_action action); + +enum wl_data_device_manager_dnd_action + meta_wayland_data_source_get_user_action (MetaWaylandDataSource *source); +void meta_wayland_data_source_set_user_action (MetaWaylandDataSource *source, + uint32_t action); + +MetaWaylandDataOffer * + meta_wayland_data_source_get_current_offer (MetaWaylandDataSource *source); +void meta_wayland_data_source_set_current_offer (MetaWaylandDataSource *source, + MetaWaylandDataOffer *offer); + +gboolean meta_wayland_data_source_get_drop_performed (MetaWaylandDataSource *source); + +void meta_wayland_data_source_notify_drop_performed (MetaWaylandDataSource *source); +void meta_wayland_data_source_notify_finish (MetaWaylandDataSource *source); + +#endif /* META_WAYLAND_DATA_SOURCE_H */ diff -Nru mutter-3.36.1/src/wayland/meta-wayland-data-source-primary.c mutter-3.36.9/src/wayland/meta-wayland-data-source-primary.c --- mutter-3.36.1/src/wayland/meta-wayland-data-source-primary.c 1970-01-01 00:00:00.000000000 +0000 +++ mutter-3.36.9/src/wayland/meta-wayland-data-source-primary.c 2021-03-15 23:07:33.325499300 +0000 @@ -0,0 +1,117 @@ +/* + * Copyright © 2011 Kristian Høgsberg + * 2020 Red Hat Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#include "config.h" + +#include + +#include "primary-selection-unstable-v1-server-protocol.h" +#include "wayland/meta-wayland-data-source-primary.h" + +typedef struct _MetaWaylandDataSourcePrimary +{ + MetaWaylandDataSource parent; +} MetaWaylandDataSourcePrimary; + +G_DEFINE_TYPE (MetaWaylandDataSourcePrimary, meta_wayland_data_source_primary, + META_TYPE_WAYLAND_DATA_SOURCE); + +static void +primary_source_offer (struct wl_client *client, + struct wl_resource *resource, + const char *type) +{ + MetaWaylandDataSource *source = wl_resource_get_user_data (resource); + + if (!meta_wayland_data_source_add_mime_type (source, type)) + wl_resource_post_no_memory (resource); +} + +static void +primary_source_destroy (struct wl_client *client, + struct wl_resource *resource) +{ + wl_resource_destroy (resource); +} + +static struct zwp_primary_selection_source_v1_interface primary_source_interface = { + primary_source_offer, + primary_source_destroy, +}; + +static void +destroy_primary_source (struct wl_resource *resource) +{ + MetaWaylandDataSource *source = wl_resource_get_user_data (resource); + + meta_wayland_data_source_set_resource (source, NULL); + g_object_unref (source); +} + +static void +meta_wayland_data_source_primary_send (MetaWaylandDataSource *source, + const gchar *mime_type, + gint fd) +{ + struct wl_resource *resource = meta_wayland_data_source_get_resource (source); + + zwp_primary_selection_source_v1_send_send (resource, mime_type, fd); + close (fd); +} + +static void +meta_wayland_data_source_primary_cancel (MetaWaylandDataSource *source) +{ + struct wl_resource *resource = meta_wayland_data_source_get_resource (source); + + if (resource) + zwp_primary_selection_source_v1_send_cancelled (resource); +} + +static void +meta_wayland_data_source_primary_init (MetaWaylandDataSourcePrimary *source_primary) +{ +} + +static void +meta_wayland_data_source_primary_class_init (MetaWaylandDataSourcePrimaryClass *klass) +{ + MetaWaylandDataSourceClass *data_source_class = + META_WAYLAND_DATA_SOURCE_CLASS (klass); + + data_source_class->send = meta_wayland_data_source_primary_send; + data_source_class->cancel = meta_wayland_data_source_primary_cancel; +} + +MetaWaylandDataSource * +meta_wayland_data_source_primary_new (struct wl_resource *resource) +{ + MetaWaylandDataSource *source_primary = + g_object_new (META_TYPE_WAYLAND_DATA_SOURCE_PRIMARY, NULL); + + meta_wayland_data_source_set_resource (source_primary, resource); + wl_resource_set_implementation (resource, &primary_source_interface, + source_primary, destroy_primary_source); + + return source_primary; +} diff -Nru mutter-3.36.1/src/wayland/meta-wayland-data-source-primary.h mutter-3.36.9/src/wayland/meta-wayland-data-source-primary.h --- mutter-3.36.1/src/wayland/meta-wayland-data-source-primary.h 1970-01-01 00:00:00.000000000 +0000 +++ mutter-3.36.9/src/wayland/meta-wayland-data-source-primary.h 2021-03-15 23:07:33.325499300 +0000 @@ -0,0 +1,37 @@ +/* + * Copyright © 2011 Kristian Høgsberg + * 2020 Red Hat Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#ifndef META_WAYLAND_DATA_SOURCE_PRIMARY_H +#define META_WAYLAND_DATA_SOURCE_PRIMARY_H + +#include "meta-wayland-data-source.h" + +#define META_TYPE_WAYLAND_DATA_SOURCE_PRIMARY (meta_wayland_data_source_primary_get_type ()) +G_DECLARE_FINAL_TYPE (MetaWaylandDataSourcePrimary, + meta_wayland_data_source_primary, + META, WAYLAND_DATA_SOURCE_PRIMARY, + MetaWaylandDataSource); + +MetaWaylandDataSource * meta_wayland_data_source_primary_new (struct wl_resource *resource); + +#endif /* META_WAYLAND_DATA_SOURCE_PRIMARY_H */ diff -Nru mutter-3.36.1/src/wayland/meta-wayland-data-source-primary-legacy.c mutter-3.36.9/src/wayland/meta-wayland-data-source-primary-legacy.c --- mutter-3.36.1/src/wayland/meta-wayland-data-source-primary-legacy.c 1970-01-01 00:00:00.000000000 +0000 +++ mutter-3.36.9/src/wayland/meta-wayland-data-source-primary-legacy.c 2021-03-15 23:07:33.325499300 +0000 @@ -0,0 +1,117 @@ +/* + * Copyright © 2011 Kristian Høgsberg + * 2020 Red Hat Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#include "config.h" + +#include + +#include "gtk-primary-selection-server-protocol.h" +#include "wayland/meta-wayland-data-source-primary-legacy.h" + +typedef struct _MetaWaylandDataSourcePrimaryLegacy +{ + MetaWaylandDataSource parent; +} MetaWaylandDataSourcePrimaryLegacy; + +G_DEFINE_TYPE (MetaWaylandDataSourcePrimaryLegacy, meta_wayland_data_source_primary_legacy, + META_TYPE_WAYLAND_DATA_SOURCE); + +static void +primary_source_offer (struct wl_client *client, + struct wl_resource *resource, + const char *type) +{ + MetaWaylandDataSource *source = wl_resource_get_user_data (resource); + + if (!meta_wayland_data_source_add_mime_type (source, type)) + wl_resource_post_no_memory (resource); +} + +static void +primary_source_destroy (struct wl_client *client, + struct wl_resource *resource) +{ + wl_resource_destroy (resource); +} + +static struct gtk_primary_selection_source_interface primary_source_interface = { + primary_source_offer, + primary_source_destroy, +}; + +static void +destroy_primary_source (struct wl_resource *resource) +{ + MetaWaylandDataSource *source = wl_resource_get_user_data (resource); + + meta_wayland_data_source_set_resource (source, NULL); + g_object_unref (source); +} + +static void +meta_wayland_data_source_primary_legacy_send (MetaWaylandDataSource *source, + const gchar *mime_type, + gint fd) +{ + struct wl_resource *resource = meta_wayland_data_source_get_resource (source); + + gtk_primary_selection_source_send_send (resource, mime_type, fd); + close (fd); +} + +static void +meta_wayland_data_source_primary_legacy_cancel (MetaWaylandDataSource *source) +{ + struct wl_resource *resource = meta_wayland_data_source_get_resource (source); + + if (resource) + gtk_primary_selection_source_send_cancelled (resource); +} + +static void +meta_wayland_data_source_primary_legacy_init (MetaWaylandDataSourcePrimaryLegacy *source_primary) +{ +} + +static void +meta_wayland_data_source_primary_legacy_class_init (MetaWaylandDataSourcePrimaryLegacyClass *klass) +{ + MetaWaylandDataSourceClass *data_source_class = + META_WAYLAND_DATA_SOURCE_CLASS (klass); + + data_source_class->send = meta_wayland_data_source_primary_legacy_send; + data_source_class->cancel = meta_wayland_data_source_primary_legacy_cancel; +} + +MetaWaylandDataSource * +meta_wayland_data_source_primary_legacy_new (struct wl_resource *resource) +{ + MetaWaylandDataSource *source_primary = + g_object_new (META_TYPE_WAYLAND_DATA_SOURCE_PRIMARY_LEGACY, NULL); + + meta_wayland_data_source_set_resource (source_primary, resource); + wl_resource_set_implementation (resource, &primary_source_interface, + source_primary, destroy_primary_source); + + return source_primary; +} diff -Nru mutter-3.36.1/src/wayland/meta-wayland-data-source-primary-legacy.h mutter-3.36.9/src/wayland/meta-wayland-data-source-primary-legacy.h --- mutter-3.36.1/src/wayland/meta-wayland-data-source-primary-legacy.h 1970-01-01 00:00:00.000000000 +0000 +++ mutter-3.36.9/src/wayland/meta-wayland-data-source-primary-legacy.h 2021-03-15 23:07:33.325499300 +0000 @@ -0,0 +1,37 @@ +/* + * Copyright © 2011 Kristian Høgsberg + * 2020 Red Hat Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#ifndef META_WAYLAND_DATA_SOURCE_PRIMARY_LEGACY_H +#define META_WAYLAND_DATA_SOURCE_PRIMARY_LEGACY_H + +#include "meta-wayland-data-source.h" + +#define META_TYPE_WAYLAND_DATA_SOURCE_PRIMARY_LEGACY (meta_wayland_data_source_primary_legacy_get_type ()) +G_DECLARE_FINAL_TYPE (MetaWaylandDataSourcePrimaryLegacy, + meta_wayland_data_source_primary_legacy, + META, WAYLAND_DATA_SOURCE_PRIMARY_LEGACY, + MetaWaylandDataSource); + +MetaWaylandDataSource * meta_wayland_data_source_primary_legacy_new (struct wl_resource *resource); + +#endif /* META_WAYLAND_DATA_SOURCE_PRIMARY_LEGACY_H */ diff -Nru mutter-3.36.1/src/wayland/meta-wayland-dnd-surface.c mutter-3.36.9/src/wayland/meta-wayland-dnd-surface.c --- mutter-3.36.1/src/wayland/meta-wayland-dnd-surface.c 2020-03-30 19:29:39.340884200 +0000 +++ mutter-3.36.9/src/wayland/meta-wayland-dnd-surface.c 2021-03-15 23:07:33.325499300 +0000 @@ -23,13 +23,13 @@ #include "backends/meta-logical-monitor.h" #include "compositor/meta-feedback-actor-private.h" +#include "wayland/meta-wayland.h" struct _MetaWaylandSurfaceRoleDND { MetaWaylandActorSurface parent; int32_t pending_offset_x; int32_t pending_offset_y; - int geometry_scale; }; G_DEFINE_TYPE (MetaWaylandSurfaceRoleDND, @@ -42,7 +42,11 @@ MetaWaylandSurface *surface = meta_wayland_surface_role_get_surface (surface_role); - meta_wayland_surface_queue_pending_frame_callbacks (surface); + if (wl_list_empty (&surface->unassigned.pending_frame_callback_list)) + return; + + meta_wayland_compositor_add_frame_callback_surface (surface->compositor, + surface); } static void @@ -56,7 +60,8 @@ MetaWaylandSurfaceRoleClass *surface_role_class = META_WAYLAND_SURFACE_ROLE_CLASS (meta_wayland_surface_role_dnd_parent_class); - meta_wayland_surface_queue_pending_state_frame_callbacks (surface, pending); + meta_wayland_compositor_add_frame_callback_surface (surface->compositor, + surface); surface_role_dnd->pending_offset_x = pending->dx; surface_role_dnd->pending_offset_y = pending->dy; @@ -117,27 +122,19 @@ geometry_scale = meta_wayland_actor_surface_get_geometry_scale (actor_surface); + meta_feedback_actor_set_geometry_scale (feedback_actor, geometry_scale); meta_feedback_actor_get_anchor (feedback_actor, &anchor_x, &anchor_y); - anchor_x -= surface_role_dnd->pending_offset_x * geometry_scale; - anchor_y -= surface_role_dnd->pending_offset_y * geometry_scale; + anchor_x -= surface_role_dnd->pending_offset_x; + anchor_y -= surface_role_dnd->pending_offset_y; meta_feedback_actor_set_anchor (feedback_actor, anchor_x, anchor_y); - if (surface_role_dnd->geometry_scale != geometry_scale) - { - surface_role_dnd->geometry_scale = geometry_scale; - clutter_actor_set_scale (CLUTTER_ACTOR (surface_actor), - geometry_scale, - geometry_scale); - } - actor_surface_class->sync_actor_state (actor_surface); } static void meta_wayland_surface_role_dnd_init (MetaWaylandSurfaceRoleDND *role) { - role->geometry_scale = 1; } static void diff -Nru mutter-3.36.1/src/wayland/meta-wayland.h mutter-3.36.9/src/wayland/meta-wayland.h --- mutter-3.36.1/src/wayland/meta-wayland.h 2020-03-30 19:29:39.349884000 +0000 +++ mutter-3.36.9/src/wayland/meta-wayland.h 2021-03-15 23:07:33.336499000 +0000 @@ -37,8 +37,10 @@ void meta_wayland_finalize (void); -/* We maintain a singleton MetaWaylandCompositor which can be got at via this - * API after meta_wayland_init() has been called. */ +MetaWaylandCompositor * meta_wayland_compositor_new (MetaBackend *backend); + +void meta_wayland_compositor_setup (MetaWaylandCompositor *compositor); + META_EXPORT_TEST MetaWaylandCompositor *meta_wayland_compositor_get_default (void); @@ -60,8 +62,11 @@ void meta_wayland_compositor_paint_finished (MetaWaylandCompositor *compositor); -void meta_wayland_compositor_destroy_frame_callbacks (MetaWaylandCompositor *compositor, - MetaWaylandSurface *surface); +void meta_wayland_compositor_add_frame_callback_surface (MetaWaylandCompositor *compositor, + MetaWaylandSurface *surface); + +void meta_wayland_compositor_remove_frame_callback_surface (MetaWaylandCompositor *compositor, + MetaWaylandSurface *surface); META_EXPORT_TEST const char *meta_wayland_get_wayland_display_name (MetaWaylandCompositor *compositor); diff -Nru mutter-3.36.1/src/wayland/meta-wayland-keyboard.c mutter-3.36.9/src/wayland/meta-wayland-keyboard.c --- mutter-3.36.1/src/wayland/meta-wayland-keyboard.c 2020-03-30 19:29:39.341884100 +0000 +++ mutter-3.36.9/src/wayland/meta-wayland-keyboard.c 2021-03-15 23:07:33.326499200 +0000 @@ -603,7 +603,6 @@ meta_wayland_keyboard_end_grab (keyboard); meta_wayland_keyboard_set_focus (keyboard, NULL); - meta_wayland_xkb_info_destroy (&keyboard->xkb_info); wl_list_remove (&keyboard->resource_list); wl_list_init (&keyboard->resource_list); @@ -918,6 +917,17 @@ } static void +meta_wayland_keyboard_finalize (GObject *object) +{ + MetaWaylandKeyboard *keyboard = META_WAYLAND_KEYBOARD (object); + + meta_wayland_xkb_info_destroy (&keyboard->xkb_info); +} + +static void meta_wayland_keyboard_class_init (MetaWaylandKeyboardClass *klass) { + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->finalize = meta_wayland_keyboard_finalize; } diff -Nru mutter-3.36.1/src/wayland/meta-wayland-legacy-xdg-shell.c mutter-3.36.9/src/wayland/meta-wayland-legacy-xdg-shell.c --- mutter-3.36.1/src/wayland/meta-wayland-legacy-xdg-shell.c 2020-03-30 19:29:39.341884100 +0000 +++ mutter-3.36.9/src/wayland/meta-wayland-legacy-xdg-shell.c 2021-03-15 23:07:33.327499200 +0000 @@ -609,8 +609,8 @@ fill_states (&states, window); zxdg_toplevel_v6_send_configure (xdg_toplevel->resource, - configuration->width, - configuration->height, + configuration->width / configuration->scale, + configuration->height / configuration->scale, &states); wl_array_release (&states); @@ -658,22 +658,20 @@ META_WAYLAND_ZXDG_SURFACE_V6 (xdg_toplevel); MetaWaylandZxdgSurfaceV6Private *xdg_surface_priv = meta_wayland_zxdg_surface_v6_get_instance_private (xdg_surface); + MetaWaylandActorSurface *actor_surface = + META_WAYLAND_ACTOR_SURFACE (xdg_surface); MetaWaylandSurfaceRoleClass *surface_role_class; MetaWaylandSurface *surface = meta_wayland_surface_role_get_surface (surface_role); MetaWindow *window; - MetaRectangle old_geometry; - gboolean geometry_changed; window = meta_wayland_surface_get_window (surface); if (!window) { - meta_wayland_surface_cache_pending_frame_callbacks (surface, pending); + meta_wayland_actor_surface_queue_frame_callbacks (actor_surface, pending); return; } - old_geometry = xdg_surface_priv->geometry; - surface_role_class = META_WAYLAND_SURFACE_ROLE_CLASS (meta_wayland_zxdg_toplevel_v6_parent_class); surface_role_class->apply_state (surface_role, pending); @@ -688,14 +686,38 @@ meta_wayland_window_configuration_free (configuration); return; } +} - if (!pending->newly_attached) - return; +static void +meta_wayland_zxdg_toplevel_v6_post_apply_state (MetaWaylandSurfaceRole *surface_role, + MetaWaylandSurfaceState *pending) +{ + MetaWaylandZxdgToplevelV6 *xdg_toplevel = + META_WAYLAND_ZXDG_TOPLEVEL_V6 (surface_role); + MetaWaylandZxdgSurfaceV6 *xdg_surface = + META_WAYLAND_ZXDG_SURFACE_V6 (xdg_toplevel); + MetaWaylandZxdgSurfaceV6Private *xdg_surface_priv = + meta_wayland_zxdg_surface_v6_get_instance_private (xdg_surface); + MetaWaylandSurfaceRoleClass *surface_role_class; + MetaWaylandSurface *surface = + meta_wayland_surface_role_get_surface (surface_role); + MetaWindow *window; + MetaRectangle old_geometry; + gboolean geometry_changed; - /* If the window disappeared the surface is not coming back. */ + window = meta_wayland_surface_get_window (surface); if (!window) return; + if (!pending->newly_attached) + return; + + old_geometry = xdg_surface_priv->geometry; + + surface_role_class = + META_WAYLAND_SURFACE_ROLE_CLASS (meta_wayland_zxdg_toplevel_v6_parent_class); + surface_role_class->post_apply_state (surface_role, pending); + geometry_changed = !meta_rectangle_equal (&old_geometry, &xdg_surface_priv->geometry); if (geometry_changed || pending->has_acked_configure_serial) @@ -734,7 +756,6 @@ wl_resource_post_error (surface->resource, ZXDG_SHELL_V6_ERROR_INVALID_SURFACE_STATE, "Invalid min/max size"); - } } } @@ -832,6 +853,8 @@ surface_role_class = META_WAYLAND_SURFACE_ROLE_CLASS (klass); surface_role_class->apply_state = meta_wayland_zxdg_toplevel_v6_apply_state; + surface_role_class->post_apply_state = + meta_wayland_zxdg_toplevel_v6_post_apply_state; surface_role_class->get_toplevel = meta_wayland_zxdg_toplevel_v6_get_toplevel; shell_surface_class = META_WAYLAND_SHELL_SURFACE_CLASS (klass); @@ -964,12 +987,7 @@ MetaWaylandSurfaceState *pending) { MetaWaylandZxdgPopupV6 *xdg_popup = META_WAYLAND_ZXDG_POPUP_V6 (surface_role); - MetaWaylandZxdgSurfaceV6 *xdg_surface = - META_WAYLAND_ZXDG_SURFACE_V6 (surface_role); MetaWaylandSurfaceRoleClass *surface_role_class; - MetaWaylandSurface *surface = - meta_wayland_surface_role_get_surface (surface_role); - MetaWindow *window; if (xdg_popup->setup.parent_surface) finish_popup_setup (xdg_popup); @@ -977,12 +995,27 @@ surface_role_class = META_WAYLAND_SURFACE_ROLE_CLASS (meta_wayland_zxdg_popup_v6_parent_class); surface_role_class->apply_state (surface_role, pending); +} + +static void +meta_wayland_zxdg_popup_v6_post_apply_state (MetaWaylandSurfaceRole *surface_role, + MetaWaylandSurfaceState *pending) +{ + MetaWaylandZxdgSurfaceV6 *xdg_surface = + META_WAYLAND_ZXDG_SURFACE_V6 (surface_role); + MetaWaylandSurfaceRoleClass *surface_role_class; + MetaWaylandSurface *surface = + meta_wayland_surface_role_get_surface (surface_role); + MetaWindow *window; - /* If the window disappeared the surface is not coming back. */ window = meta_wayland_surface_get_window (surface); if (!window) return; + surface_role_class = + META_WAYLAND_SURFACE_ROLE_CLASS (meta_wayland_zxdg_popup_v6_parent_class); + surface_role_class->post_apply_state (surface_role, pending); + if (!pending->newly_attached) return; @@ -1042,7 +1075,8 @@ zxdg_popup_v6_send_configure (xdg_popup->resource, x, y, - configuration->width, configuration->height); + configuration->width / configuration->scale, + configuration->height / configuration->scale); meta_wayland_zxdg_surface_v6_send_configure (xdg_surface, configuration); } @@ -1165,6 +1199,8 @@ surface_role_class = META_WAYLAND_SURFACE_ROLE_CLASS (klass); surface_role_class->apply_state = meta_wayland_zxdg_popup_v6_apply_state; + surface_role_class->post_apply_state = + meta_wayland_zxdg_popup_v6_post_apply_state; surface_role_class->get_toplevel = meta_wayland_zxdg_popup_v6_get_toplevel; shell_surface_class = META_WAYLAND_SHELL_SURFACE_CLASS (klass); @@ -1218,14 +1254,10 @@ static void zxdg_surface_v6_destructor (struct wl_resource *resource) { - MetaWaylandSurface *surface = surface_from_xdg_surface_resource (resource); MetaWaylandZxdgSurfaceV6 *xdg_surface = wl_resource_get_user_data (resource); MetaWaylandZxdgSurfaceV6Private *priv = meta_wayland_zxdg_surface_v6_get_instance_private (xdg_surface); - meta_wayland_compositor_destroy_frame_callbacks (surface->compositor, - surface); - priv->shell_client->surfaces = g_list_remove (priv->shell_client->surfaces, xdg_surface); @@ -1331,8 +1363,6 @@ { MetaWaylandZxdgSurfaceV6 *xdg_surface = META_WAYLAND_ZXDG_SURFACE_V6 (surface_role); - MetaWaylandShellSurface *shell_surface = - META_WAYLAND_SHELL_SURFACE (xdg_surface); MetaWaylandZxdgSurfaceV6Private *priv = meta_wayland_zxdg_surface_v6_get_instance_private (xdg_surface); MetaWaylandSurface *surface = @@ -1370,8 +1400,18 @@ if (surface->buffer_ref.buffer) priv->first_buffer_attached = TRUE; - else - return; +} + +static void +meta_wayland_zxdg_surface_v6_post_apply_state (MetaWaylandSurfaceRole *surface_role, + MetaWaylandSurfaceState *pending) +{ + MetaWaylandZxdgSurfaceV6 *xdg_surface = + META_WAYLAND_ZXDG_SURFACE_V6 (surface_role); + MetaWaylandZxdgSurfaceV6Private *priv = + meta_wayland_zxdg_surface_v6_get_instance_private (xdg_surface); + MetaWaylandShellSurface *shell_surface = + META_WAYLAND_SHELL_SURFACE (xdg_surface); if (pending->has_new_geometry) { @@ -1526,6 +1566,8 @@ surface_role_class = META_WAYLAND_SURFACE_ROLE_CLASS (klass); surface_role_class->apply_state = meta_wayland_zxdg_surface_v6_apply_state; + surface_role_class->post_apply_state = + meta_wayland_zxdg_surface_v6_post_apply_state; surface_role_class->assigned = meta_wayland_zxdg_surface_v6_assigned; shell_surface_class = META_WAYLAND_SHELL_SURFACE_CLASS (klass); diff -Nru mutter-3.36.1/src/wayland/meta-wayland-pointer-constraints.c mutter-3.36.9/src/wayland/meta-wayland-pointer-constraints.c --- mutter-3.36.1/src/wayland/meta-wayland-pointer-constraints.c 2020-03-30 19:29:39.342884000 +0000 +++ mutter-3.36.9/src/wayland/meta-wayland-pointer-constraints.c 2021-03-15 23:07:33.328499000 +0000 @@ -625,12 +625,15 @@ frame->right_width); actual_height = window->buffer_rect.height - (frame->child_y + frame->bottom_height); - cairo_region_intersect_rectangle (region, &(cairo_rectangle_int_t) { - .x = frame->child_x, - .y = frame->child_y, - .width = actual_width, - .height = actual_height - }); + if (actual_width > 0 && actual_height > 0) + { + cairo_region_intersect_rectangle (region, &(cairo_rectangle_int_t) { + .x = frame->child_x, + .y = frame->child_y, + .width = actual_width, + .height = actual_height + }); + } } return region; diff -Nru mutter-3.36.1/src/wayland/meta-wayland-private.h mutter-3.36.9/src/wayland/meta-wayland-private.h --- mutter-3.36.1/src/wayland/meta-wayland-private.h 2020-03-30 19:29:39.343884000 +0000 +++ mutter-3.36.9/src/wayland/meta-wayland-private.h 2021-03-15 23:07:33.329499200 +0000 @@ -74,10 +74,12 @@ { GObject parent; + MetaBackend *backend; + struct wl_display *wayland_display; char *display_name; GHashTable *outputs; - struct wl_list frame_callbacks; + GList *frame_callback_surfaces; MetaXWaylandManager xwayland_manager; diff -Nru mutter-3.36.1/src/wayland/meta-wayland-seat.c mutter-3.36.9/src/wayland/meta-wayland-seat.c --- mutter-3.36.1/src/wayland/meta-wayland-seat.c 2020-03-30 19:29:39.343884000 +0000 +++ mutter-3.36.9/src/wayland/meta-wayland-seat.c 2021-03-15 23:07:33.329499200 +0000 @@ -24,6 +24,7 @@ #include "wayland/meta-wayland-seat.h" #include "wayland/meta-wayland-data-device.h" +#include "wayland/meta-wayland-data-device-primary-legacy.h" #include "wayland/meta-wayland-private.h" #include "wayland/meta-wayland-tablet-seat.h" #include "wayland/meta-wayland-versions.h" @@ -73,10 +74,18 @@ meta_wayland_touch_create_new_resource (touch, client, resource, id); } +static void +seat_release (struct wl_client *client, + struct wl_resource *resource) +{ + wl_resource_destroy (resource); +} + static const struct wl_seat_interface seat_interface = { seat_get_pointer, seat_get_keyboard, - seat_get_touch + seat_get_touch, + seat_release }; static void @@ -231,6 +240,8 @@ seat->gtk_text_input = meta_wayland_gtk_text_input_new (seat); meta_wayland_data_device_init (&seat->data_device); + meta_wayland_data_device_primary_init (&seat->primary_data_device); + meta_wayland_data_device_primary_legacy_init (&seat->primary_legacy_data_device); clutter_seat = clutter_backend_get_default_seat (clutter_get_default_backend ()); meta_wayland_seat_update_capabilities (seat, clutter_seat); @@ -404,6 +415,16 @@ return meta_wayland_touch_handle_event (seat->touch, event); break; + case CLUTTER_IM_COMMIT: + case CLUTTER_IM_DELETE: + case CLUTTER_IM_PREEDIT: + if (meta_wayland_text_input_handle_event (seat->text_input, event)) + return TRUE; + if (meta_wayland_gtk_text_input_handle_event (seat->gtk_text_input, + event)) + return TRUE; + + break; default: break; } @@ -431,6 +452,8 @@ { meta_wayland_keyboard_set_focus (seat->keyboard, surface); meta_wayland_data_device_set_keyboard_focus (&seat->data_device); + meta_wayland_data_device_primary_set_keyboard_focus (&seat->primary_data_device); + meta_wayland_data_device_primary_legacy_set_keyboard_focus (&seat->primary_legacy_data_device); } tablet_seat = meta_wayland_tablet_manager_ensure_seat (compositor->tablet_manager, seat); diff -Nru mutter-3.36.1/src/wayland/meta-wayland-seat.h mutter-3.36.9/src/wayland/meta-wayland-seat.h --- mutter-3.36.1/src/wayland/meta-wayland-seat.h 2020-03-30 19:29:39.344884200 +0000 +++ mutter-3.36.9/src/wayland/meta-wayland-seat.h 2021-03-15 23:07:33.329499200 +0000 @@ -26,6 +26,8 @@ #include "clutter/clutter.h" #include "wayland/meta-wayland-data-device.h" +#include "wayland/meta-wayland-data-device-primary.h" +#include "wayland/meta-wayland-data-device-primary-legacy.h" #include "wayland/meta-wayland-input-device.h" #include "wayland/meta-wayland-keyboard.h" #include "wayland/meta-wayland-pointer.h" @@ -45,6 +47,8 @@ MetaWaylandTouch *touch; MetaWaylandDataDevice data_device; + MetaWaylandDataDevicePrimary primary_data_device; + MetaWaylandDataDevicePrimaryLegacy primary_legacy_data_device; MetaWaylandGtkTextInput *gtk_text_input; MetaWaylandTextInput *text_input; diff -Nru mutter-3.36.1/src/wayland/meta-wayland-subsurface.c mutter-3.36.9/src/wayland/meta-wayland-subsurface.c --- mutter-3.36.1/src/wayland/meta-wayland-subsurface.c 2020-03-30 19:29:39.344884200 +0000 +++ mutter-3.36.9/src/wayland/meta-wayland-subsurface.c 2021-03-15 23:07:33.330499200 +0000 @@ -30,19 +30,6 @@ #include "wayland/meta-wayland-surface.h" #include "wayland/meta-window-wayland.h" -typedef enum -{ - META_WAYLAND_SUBSURFACE_PLACEMENT_ABOVE, - META_WAYLAND_SUBSURFACE_PLACEMENT_BELOW -} MetaWaylandSubsurfacePlacement; - -typedef struct -{ - MetaWaylandSubsurfacePlacement placement; - MetaWaylandSurface *sibling; - struct wl_listener sibling_destroy_listener; -} MetaWaylandSubsurfacePlacementOp; - struct _MetaWaylandSubsurface { MetaWaylandActorSurface parent; @@ -135,57 +122,6 @@ surface->sub.pending_pos = FALSE; } - if (surface->sub.pending_placement_ops) - { - GSList *it; - MetaWaylandSurface *parent; - - parent = surface->sub.parent; - - for (it = surface->sub.pending_placement_ops; it; it = it->next) - { - MetaWaylandSubsurfacePlacementOp *op = it->data; - MetaWaylandSurface *sibling; - GNode *sibling_node; - - if (!op->sibling) - { - g_slice_free (MetaWaylandSubsurfacePlacementOp, op); - continue; - } - - sibling = op->sibling; - if (is_child (surface, sibling)) - sibling_node = sibling->subsurface_leaf_node; - else - sibling_node = sibling->subsurface_branch_node; - - g_node_unlink (surface->subsurface_branch_node); - - switch (op->placement) - { - case META_WAYLAND_SUBSURFACE_PLACEMENT_ABOVE: - g_node_insert_after (parent->subsurface_branch_node, - sibling_node, - surface->subsurface_branch_node); - break; - case META_WAYLAND_SUBSURFACE_PLACEMENT_BELOW: - g_node_insert_before (parent->subsurface_branch_node, - sibling_node, - surface->subsurface_branch_node); - break; - } - - wl_list_remove (&op->sibling_destroy_listener.link); - g_slice_free (MetaWaylandSubsurfacePlacementOp, op); - } - - g_slist_free (surface->sub.pending_placement_ops); - surface->sub.pending_placement_ops = NULL; - - meta_wayland_surface_notify_subsurface_state_changed (parent); - } - if (is_surface_effectively_synchronized (surface)) meta_wayland_surface_apply_cached_state (surface); @@ -275,7 +211,8 @@ meta_wayland_surface_role_get_surface (surface_role); MetaWaylandSurface *parent = surface->sub.parent; - return meta_wayland_surface_notify_subsurface_state_changed (parent); + if (parent) + return meta_wayland_surface_notify_subsurface_state_changed (parent); } static double @@ -362,9 +299,6 @@ { MetaWaylandSurface *surface = wl_resource_get_user_data (resource); - meta_wayland_compositor_destroy_frame_callbacks (surface->compositor, - surface); - g_node_unlink (surface->subsurface_branch_node); unparent_actor (surface); @@ -409,6 +343,16 @@ } static void +subsurface_handle_pending_surface_destroyed (struct wl_listener *listener, + void *data) +{ + MetaWaylandSubsurfacePlacementOp *op = + wl_container_of (listener, op, surface_destroy_listener); + + op->surface = NULL; +} + +static void subsurface_handle_pending_sibling_destroyed (struct wl_listener *listener, void *data) { @@ -418,23 +362,39 @@ op->sibling = NULL; } +void +meta_wayland_subsurface_placement_op_free (MetaWaylandSubsurfacePlacementOp *op) +{ + if (op->surface) + wl_list_remove (&op->surface_destroy_listener.link); + if (op->sibling) + wl_list_remove (&op->sibling_destroy_listener.link); + g_free (op); +} + static void queue_subsurface_placement (MetaWaylandSurface *surface, MetaWaylandSurface *sibling, MetaWaylandSubsurfacePlacement placement) { + MetaWaylandSurface *parent = surface->sub.parent; MetaWaylandSubsurfacePlacementOp *op = - g_slice_new (MetaWaylandSubsurfacePlacementOp); + g_new0 (MetaWaylandSubsurfacePlacementOp, 1); op->placement = placement; + op->surface = surface; op->sibling = sibling; + op->surface_destroy_listener.notify = + subsurface_handle_pending_surface_destroyed; op->sibling_destroy_listener.notify = subsurface_handle_pending_sibling_destroyed; + wl_resource_add_destroy_listener (surface->resource, + &op->surface_destroy_listener); wl_resource_add_destroy_listener (sibling->resource, &op->sibling_destroy_listener); - surface->sub.pending_placement_ops = - g_slist_append (surface->sub.pending_placement_ops, op); + parent->pending_state->subsurface_placement_ops = + g_slist_append (parent->pending_state->subsurface_placement_ops, op); } static void @@ -532,6 +492,17 @@ surface->sub.parent = NULL; } +static gboolean +is_same_or_ancestor (MetaWaylandSurface *surface, + MetaWaylandSurface *other_surface) +{ + if (surface == other_surface) + return TRUE; + if (other_surface->sub.parent) + return is_same_or_ancestor (surface, other_surface->sub.parent); + return FALSE; +} + static void wl_subcompositor_get_subsurface (struct wl_client *client, struct wl_resource *resource, @@ -551,6 +522,16 @@ return; } + if (is_same_or_ancestor (surface, parent)) + { + wl_resource_post_error (resource, WL_SUBCOMPOSITOR_ERROR_BAD_SURFACE, + "Circular relationship between wl_surface@%d " + "and parent surface wl_surface@%d", + wl_resource_get_id (surface->resource), + wl_resource_get_id (parent->resource)); + return; + } + if (!meta_wayland_surface_assign_role (surface, META_TYPE_WAYLAND_SUBSURFACE, NULL)) diff -Nru mutter-3.36.1/src/wayland/meta-wayland-subsurface.h mutter-3.36.9/src/wayland/meta-wayland-subsurface.h --- mutter-3.36.1/src/wayland/meta-wayland-subsurface.h 2020-03-30 19:29:39.344884200 +0000 +++ mutter-3.36.9/src/wayland/meta-wayland-subsurface.h 2021-03-15 23:07:33.330499200 +0000 @@ -29,6 +29,21 @@ META, WAYLAND_SUBSURFACE, MetaWaylandActorSurface) +typedef enum +{ + META_WAYLAND_SUBSURFACE_PLACEMENT_ABOVE, + META_WAYLAND_SUBSURFACE_PLACEMENT_BELOW +} MetaWaylandSubsurfacePlacement; + +typedef struct +{ + MetaWaylandSubsurfacePlacement placement; + MetaWaylandSurface *surface; + MetaWaylandSurface *sibling; + struct wl_listener surface_destroy_listener; + struct wl_listener sibling_destroy_listener; +} MetaWaylandSubsurfacePlacementOp; + void meta_wayland_subsurface_parent_state_applied (MetaWaylandSubsurface *subsurface); void meta_wayland_subsurface_union_geometry (MetaWaylandSubsurface *subsurface, @@ -36,6 +51,8 @@ int parent_y, MetaRectangle *out_geometry); +void meta_wayland_subsurface_placement_op_free (MetaWaylandSubsurfacePlacementOp *op); + void meta_wayland_subsurfaces_init (MetaWaylandCompositor *compositor); #endif /* META_WAYLAND_SUBSURFACE_H */ diff -Nru mutter-3.36.1/src/wayland/meta-wayland-surface.c mutter-3.36.9/src/wayland/meta-wayland-surface.c --- mutter-3.36.1/src/wayland/meta-wayland-surface.c 2020-03-30 19:29:39.345884000 +0000 +++ mutter-3.36.9/src/wayland/meta-wayland-surface.c 2021-03-15 23:07:33.331499000 +0000 @@ -113,6 +113,10 @@ meta_wayland_surface_role_apply_state (MetaWaylandSurfaceRole *surface_role, MetaWaylandSurfaceState *pending); +static void +meta_wayland_surface_role_post_apply_state (MetaWaylandSurfaceRole *surface_role, + MetaWaylandSurfaceState *pending); + static gboolean meta_wayland_surface_role_is_on_logical_monitor (MetaWaylandSurfaceRole *surface_role, MetaLogicalMonitor *logical_monitor); @@ -352,15 +356,6 @@ cairo_region_destroy (transformed_region); } -void -meta_wayland_surface_queue_pending_state_frame_callbacks (MetaWaylandSurface *surface, - MetaWaylandSurfaceState *pending) -{ - wl_list_insert_list (&surface->compositor->frame_callbacks, - &pending->frame_callback_list); - wl_list_init (&pending->frame_callback_list); -} - MetaWaylandBuffer * meta_wayland_surface_get_buffer (MetaWaylandSurface *surface) { @@ -426,6 +421,8 @@ state->has_new_buffer_transform = FALSE; state->has_new_viewport_src_rect = FALSE; state->has_new_viewport_dst_size = FALSE; + + state->subsurface_placement_ops = NULL; } static void @@ -443,6 +440,13 @@ wl_list_for_each_safe (cb, next, &state->frame_callback_list, link) wl_resource_destroy (cb->resource); + + if (state->subsurface_placement_ops) + { + g_slist_free_full ( + state->subsurface_placement_ops, + (GDestroyNotify) meta_wayland_subsurface_placement_op_free); + } } static void @@ -558,6 +562,22 @@ to); } + if (from->subsurface_placement_ops != NULL) + { + if (to->subsurface_placement_ops != NULL) + { + to->subsurface_placement_ops = + g_slist_concat (to->subsurface_placement_ops, + from->subsurface_placement_ops); + } + else + { + to->subsurface_placement_ops = from->subsurface_placement_ops; + } + + from->subsurface_placement_ops = NULL; + } + meta_wayland_surface_state_set_default (from); } @@ -593,15 +613,6 @@ G_TYPE_NONE, 0); } -void -meta_wayland_surface_cache_pending_frame_callbacks (MetaWaylandSurface *surface, - MetaWaylandSurfaceState *pending) -{ - wl_list_insert_list (&surface->pending_frame_callback_list, - &pending->frame_callback_list); - wl_list_init (&pending->frame_callback_list); -} - static void meta_wayland_surface_apply_state (MetaWaylandSurface *surface, MetaWaylandSurfaceState *state) @@ -731,7 +742,9 @@ } else { - meta_wayland_surface_cache_pending_frame_callbacks (surface, state); + wl_list_insert_list (surface->unassigned.pending_frame_callback_list.prev, + &state->frame_callback_list); + wl_list_init (&state->frame_callback_list); if (state->newly_attached) { @@ -745,6 +758,43 @@ } } + if (state->subsurface_placement_ops) + { + GSList *l; + + for (l = state->subsurface_placement_ops; l; l = l->next) + { + MetaWaylandSubsurfacePlacementOp *op = l->data; + GNode *sibling_node; + + if (!op->surface || !op->sibling) + continue; + + if (op->sibling == surface) + sibling_node = surface->subsurface_leaf_node; + else + sibling_node = op->sibling->subsurface_branch_node; + + g_node_unlink (op->surface->subsurface_branch_node); + + switch (op->placement) + { + case META_WAYLAND_SUBSURFACE_PLACEMENT_ABOVE: + g_node_insert_after (surface->subsurface_branch_node, + sibling_node, + op->surface->subsurface_branch_node); + break; + case META_WAYLAND_SUBSURFACE_PLACEMENT_BELOW: + g_node_insert_before (surface->subsurface_branch_node, + sibling_node, + op->surface->subsurface_branch_node); + break; + } + } + + meta_wayland_surface_notify_subsurface_state_changed (surface); + } + cleanup: /* If we have a buffer that we are not using, decrease the use count so it may * be released if no-one else has a use-reference to it. @@ -757,8 +807,6 @@ surface_state_signals[SURFACE_STATE_SIGNAL_APPLIED], 0); - meta_wayland_surface_state_reset (state); - META_WAYLAND_SURFACE_FOREACH_SUBSURFACE (surface, subsurface_surface) { MetaWaylandSubsurface *subsurface; @@ -782,6 +830,11 @@ meta_window_actor_notify_damaged (toplevel_window_actor); } } + + if (surface->role) + meta_wayland_surface_role_post_apply_state (surface->role, state); + + meta_wayland_surface_state_reset (state); } void @@ -1288,14 +1341,16 @@ if (surface->input_region) cairo_region_destroy (surface->input_region); - meta_wayland_compositor_destroy_frame_callbacks (compositor, surface); + meta_wayland_compositor_remove_frame_callback_surface (compositor, 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) + wl_list_for_each_safe (cb, next, + &surface->unassigned.pending_frame_callback_list, + link) wl_resource_destroy (cb->resource); if (surface->resource) @@ -1342,7 +1397,7 @@ surface, wl_surface_destructor); - wl_list_init (&surface->pending_frame_callback_list); + wl_list_init (&surface->unassigned.pending_frame_callback_list); surface->outputs_to_destroy_notify_id = g_hash_table_new (NULL, NULL); surface->shortcut_inhibited_seats = g_hash_table_new (NULL, NULL); @@ -1697,6 +1752,17 @@ } static void +meta_wayland_surface_role_post_apply_state (MetaWaylandSurfaceRole *surface_role, + MetaWaylandSurfaceState *pending) +{ + MetaWaylandSurfaceRoleClass *klass; + + klass = META_WAYLAND_SURFACE_ROLE_GET_CLASS (surface_role); + if (klass->post_apply_state) + klass->post_apply_state (surface_role, pending); +} + +static void meta_wayland_surface_role_apply_state (MetaWaylandSurfaceRole *surface_role, MetaWaylandSurfaceState *pending) { @@ -1799,14 +1865,6 @@ return priv->surface; } -void -meta_wayland_surface_queue_pending_frame_callbacks (MetaWaylandSurface *surface) -{ - wl_list_insert_list (&surface->compositor->frame_callbacks, - &surface->pending_frame_callback_list); - wl_list_init (&surface->pending_frame_callback_list); -} - cairo_region_t * meta_wayland_surface_calculate_input_region (MetaWaylandSurface *surface) { diff -Nru mutter-3.36.1/src/wayland/meta-wayland-surface.h mutter-3.36.9/src/wayland/meta-wayland-surface.h --- mutter-3.36.1/src/wayland/meta-wayland-surface.h 2020-03-30 19:29:39.345884000 +0000 +++ mutter-3.36.9/src/wayland/meta-wayland-surface.h 2021-03-15 23:07:33.331499000 +0000 @@ -58,6 +58,8 @@ MetaWaylandSurfaceState *pending); void (*apply_state) (MetaWaylandSurfaceRole *surface_role, MetaWaylandSurfaceState *pending); + void (*post_apply_state) (MetaWaylandSurfaceRole *surface_role, + MetaWaylandSurfaceState *pending); gboolean (*is_on_logical_monitor) (MetaWaylandSurfaceRole *surface_role, MetaLogicalMonitor *logical_monitor); MetaWaylandSurface * (*get_toplevel) (MetaWaylandSurfaceRole *surface_role); @@ -118,6 +120,8 @@ gboolean has_new_viewport_dst_size; int viewport_dst_width; int viewport_dst_height; + + GSList *subsurface_placement_ops; }; struct _MetaWaylandDragDestFuncs @@ -164,13 +168,9 @@ /* Buffer renderer state. */ gboolean buffer_held; - /* List of pending frame callbacks that needs to stay queued longer than one - * commit sequence, such as when it has not yet been assigned a role. - */ - struct wl_list pending_frame_callback_list; - /* Intermediate state for when no role has been assigned. */ struct { + struct wl_list pending_frame_callback_list; MetaWaylandBuffer *buffer; } unassigned; @@ -207,7 +207,6 @@ int32_t pending_x; int32_t pending_y; gboolean pending_pos; - GSList *pending_placement_ops; } sub; /* wp_viewport */ @@ -284,9 +283,6 @@ MetaWindow * meta_wayland_surface_get_toplevel_window (MetaWaylandSurface *surface); -void meta_wayland_surface_cache_pending_frame_callbacks (MetaWaylandSurface *surface, - MetaWaylandSurfaceState *pending); - void meta_wayland_surface_queue_pending_frame_callbacks (MetaWaylandSurface *surface); void meta_wayland_surface_queue_pending_state_frame_callbacks (MetaWaylandSurface *surface, diff -Nru mutter-3.36.1/src/wayland/meta-wayland-text-input.c mutter-3.36.9/src/wayland/meta-wayland-text-input.c --- mutter-3.36.1/src/wayland/meta-wayland-text-input.c 2020-03-30 19:29:39.347884000 +0000 +++ mutter-3.36.9/src/wayland/meta-wayland-text-input.c 2021-03-15 23:07:33.333499000 +0000 @@ -118,10 +118,9 @@ GUINT_TO_POINTER (serial + 1)); } -static gboolean -done_idle_cb (gpointer user_data) +static void +clutter_input_focus_send_done (ClutterInputFocus *focus) { - ClutterInputFocus *focus = user_data; MetaWaylandTextInput *text_input; struct wl_resource *resource; @@ -132,6 +131,16 @@ zwp_text_input_v3_send_done (resource, lookup_serial (text_input, resource)); } +} + +static gboolean +done_idle_cb (gpointer user_data) +{ + ClutterInputFocus *focus = user_data; + MetaWaylandTextInput *text_input; + + text_input = META_WAYLAND_TEXT_INPUT_FOCUS (focus)->text_input; + clutter_input_focus_send_done (focus); text_input->done_idle_id = 0; return G_SOURCE_REMOVE; @@ -147,24 +156,35 @@ if (text_input->done_idle_id != 0) return; - /* This operates on 3 principles: - * - GDBus uses G_PRIORITY_DEFAULT to put messages in the thread default main - * context. - * - All relevant ClutterInputFocus methods are ultimately backed by - * DBus methods inside IBus. + /* This operates on 2 principles: + * - IM operations come as individual ClutterEvents * - We want to run .done after them all. The slightly lower * G_PRIORITY_DEFAULT + 1 priority should ensure we at least group - * all messages seen so far. + * all events seen so far. * * FIXME: .done may be delayed indefinitely if there's a high enough * priority idle source in the main loop. It's unlikely that * recurring idles run at this high priority though. */ - text_input->done_idle_id = g_idle_add_full (G_PRIORITY_DEFAULT + 1, + text_input->done_idle_id = g_idle_add_full (CLUTTER_PRIORITY_EVENTS + 1, done_idle_cb, focus, NULL); } static void +meta_wayland_text_input_focus_flush_done (ClutterInputFocus *focus) +{ + MetaWaylandTextInput *text_input; + + text_input = META_WAYLAND_TEXT_INPUT_FOCUS (focus)->text_input; + + if (text_input->done_idle_id == 0) + return; + + g_clear_handle_id (&text_input->done_idle_id, g_source_remove); + clutter_input_focus_send_done (focus); +} + +static void meta_wayland_text_input_focus_delete_surrounding (ClutterInputFocus *focus, int offset, guint len) @@ -737,6 +757,10 @@ !clutter_input_focus_is_focused (text_input->input_focus)) return FALSE; - return clutter_input_focus_filter_key_event (text_input->input_focus, - (const ClutterKeyEvent *) event); + if ((event->type == CLUTTER_KEY_PRESS || + event->type == CLUTTER_KEY_RELEASE) && + clutter_event_get_flags (event) & CLUTTER_EVENT_FLAG_INPUT_METHOD) + meta_wayland_text_input_focus_flush_done (text_input->input_focus); + + return clutter_input_focus_filter_event (text_input->input_focus, event); } diff -Nru mutter-3.36.1/src/wayland/meta-wayland-text-input-legacy.c mutter-3.36.9/src/wayland/meta-wayland-text-input-legacy.c --- mutter-3.36.1/src/wayland/meta-wayland-text-input-legacy.c 2020-03-30 19:29:39.347884000 +0000 +++ mutter-3.36.9/src/wayland/meta-wayland-text-input-legacy.c 2021-03-15 23:07:33.333499000 +0000 @@ -629,6 +629,5 @@ !clutter_input_focus_is_focused (text_input->input_focus)) return FALSE; - return clutter_input_focus_filter_key_event (text_input->input_focus, - (const ClutterKeyEvent *) event); + return clutter_input_focus_filter_event (text_input->input_focus, event); } diff -Nru mutter-3.36.1/src/wayland/meta-wayland-types.h mutter-3.36.9/src/wayland/meta-wayland-types.h --- mutter-3.36.1/src/wayland/meta-wayland-types.h 2020-03-30 19:29:39.347884000 +0000 +++ mutter-3.36.9/src/wayland/meta-wayland-types.h 2021-03-15 23:07:33.333499000 +0000 @@ -37,6 +37,8 @@ typedef struct _MetaWaylandDragDestFuncs MetaWaylandDragDestFuncs; typedef struct _MetaWaylandDataOffer MetaWaylandDataOffer; typedef struct _MetaWaylandDataDevice MetaWaylandDataDevice; +typedef struct _MetaWaylandDataDevicePrimary MetaWaylandDataDevicePrimary; +typedef struct _MetaWaylandDataDevicePrimaryLegacy MetaWaylandDataDevicePrimaryLegacy; typedef struct _MetaWaylandTabletManager MetaWaylandTabletManager; typedef struct _MetaWaylandTabletSeat MetaWaylandTabletSeat; diff -Nru mutter-3.36.1/src/wayland/meta-wayland-window-configuration.c mutter-3.36.9/src/wayland/meta-wayland-window-configuration.c --- mutter-3.36.1/src/wayland/meta-wayland-window-configuration.c 2020-03-30 19:29:39.348883900 +0000 +++ mutter-3.36.9/src/wayland/meta-wayland-window-configuration.c 2021-03-15 23:07:33.334499100 +0000 @@ -29,6 +29,7 @@ int y, int width, int height, + int scale, MetaMoveResizeFlags flags, MetaGravity gravity) { @@ -46,6 +47,7 @@ .width = width, .height = height, + .scale = scale, .gravity = gravity, .flags = flags, }; @@ -57,7 +59,8 @@ meta_wayland_window_configuration_new_relative (int rel_x, int rel_y, int width, - int height) + int height, + int scale) { MetaWaylandWindowConfiguration *configuration; @@ -72,6 +75,8 @@ .has_size = TRUE, .width = width, .height = height, + + .scale = scale, }; return configuration; @@ -85,6 +90,7 @@ configuration = g_new0 (MetaWaylandWindowConfiguration, 1); *configuration = (MetaWaylandWindowConfiguration) { .serial = ++global_serial_counter, + .scale = 1, }; return configuration; diff -Nru mutter-3.36.1/src/wayland/meta-wayland-window-configuration.h mutter-3.36.9/src/wayland/meta-wayland-window-configuration.h --- mutter-3.36.1/src/wayland/meta-wayland-window-configuration.h 2020-03-30 19:29:39.348883900 +0000 +++ mutter-3.36.9/src/wayland/meta-wayland-window-configuration.h 2021-03-15 23:07:33.334499100 +0000 @@ -43,6 +43,7 @@ int width; int height; + int scale; MetaGravity gravity; MetaMoveResizeFlags flags; }; @@ -51,13 +52,15 @@ int y, int width, int height, + int scale, MetaMoveResizeFlags flags, MetaGravity gravity); MetaWaylandWindowConfiguration * meta_wayland_window_configuration_new_relative (int rel_x, int rel_y, int width, - int height); + int height, + int scale); MetaWaylandWindowConfiguration * meta_wayland_window_configuration_new_empty (void); diff -Nru mutter-3.36.1/src/wayland/meta-wayland-wl-shell.c mutter-3.36.9/src/wayland/meta-wayland-wl-shell.c --- mutter-3.36.1/src/wayland/meta-wayland-wl-shell.c 2020-03-30 19:29:39.348883900 +0000 +++ mutter-3.36.9/src/wayland/meta-wayland-wl-shell.c 2021-03-15 23:07:33.334499100 +0000 @@ -103,9 +103,6 @@ surface_from_wl_shell_surface_resource (resource); GList *l; - meta_wayland_compositor_destroy_frame_callbacks (surface->compositor, - surface); - if (wl_shell_surface->popup) meta_wayland_popup_dismiss (wl_shell_surface->popup); @@ -660,7 +657,8 @@ wl_shell_surface_send_configure (wl_shell_surface->resource, 0, - configuration->width, configuration->height); + configuration->width / configuration->scale, + configuration->height / configuration->scale); wl_shell_surface->emulated_ack_configure_serial = configuration->serial; } diff -Nru mutter-3.36.1/src/wayland/meta-wayland-xdg-shell.c mutter-3.36.9/src/wayland/meta-wayland-xdg-shell.c --- mutter-3.36.1/src/wayland/meta-wayland-xdg-shell.c 2020-03-30 19:29:39.348883900 +0000 +++ mutter-3.36.9/src/wayland/meta-wayland-xdg-shell.c 2021-03-15 23:07:33.335499000 +0000 @@ -171,6 +171,10 @@ surface_from_xdg_surface_resource (struct wl_resource *resource) { MetaWaylandSurfaceRole *surface_role = wl_resource_get_user_data (resource); + + if (!META_IS_WAYLAND_SURFACE_ROLE (surface_role)) + return NULL; + return meta_wayland_surface_role_get_surface (surface_role); } @@ -693,8 +697,8 @@ fill_states (xdg_toplevel, &states); xdg_toplevel_send_configure (xdg_toplevel->resource, - configuration->width, - configuration->height, + configuration->width / configuration->scale, + configuration->height / configuration->scale, &states); wl_array_release (&states); @@ -740,33 +744,28 @@ MetaWaylandXdgSurface *xdg_surface = META_WAYLAND_XDG_SURFACE (xdg_toplevel); MetaWaylandXdgSurfacePrivate *xdg_surface_priv = meta_wayland_xdg_surface_get_instance_private (xdg_surface); + MetaWaylandActorSurface *actor_surface = + META_WAYLAND_ACTOR_SURFACE (xdg_toplevel); MetaWaylandSurfaceRoleClass *surface_role_class; MetaWaylandSurface *surface = meta_wayland_surface_role_get_surface (surface_role); MetaWindow *window; - MetaRectangle old_geometry; - gboolean geometry_changed; window = meta_wayland_surface_get_window (surface); if (!window) { - meta_wayland_surface_cache_pending_frame_callbacks (surface, pending); + meta_wayland_actor_surface_queue_frame_callbacks (actor_surface, pending); return; } if (!surface->buffer_ref.buffer && xdg_surface_priv->first_buffer_attached) { - MetaWaylandActorSurface *actor_surface = - META_WAYLAND_ACTOR_SURFACE (xdg_toplevel); - meta_wayland_xdg_surface_reset (xdg_surface); meta_wayland_actor_surface_queue_frame_callbacks (actor_surface, pending); return; } - old_geometry = xdg_surface_priv->geometry; - surface_role_class = META_WAYLAND_SURFACE_ROLE_CLASS (meta_wayland_xdg_toplevel_parent_class); surface_role_class->apply_state (surface_role, pending); @@ -780,17 +779,42 @@ meta_wayland_window_configuration_free (configuration); return; } +} + +static void +meta_wayland_xdg_toplevel_post_apply_state (MetaWaylandSurfaceRole *surface_role, + MetaWaylandSurfaceState *pending) +{ + MetaWaylandXdgSurface *xdg_surface = META_WAYLAND_XDG_SURFACE (surface_role); + MetaWaylandXdgSurfacePrivate *xdg_surface_priv = + meta_wayland_xdg_surface_get_instance_private (xdg_surface); + MetaWaylandSurface *surface = + meta_wayland_surface_role_get_surface (surface_role); + MetaWaylandSurfaceRoleClass *surface_role_class; + MetaWindow *window; + MetaRectangle old_geometry; + MetaRectangle window_geometry; + + gboolean geometry_changed; + + window = meta_wayland_surface_get_window (surface); + if (!window) + return; + + old_geometry = xdg_surface_priv->geometry; + + surface_role_class = + META_WAYLAND_SURFACE_ROLE_CLASS (meta_wayland_xdg_toplevel_parent_class); + surface_role_class->post_apply_state (surface_role, pending); if (!pending->newly_attached) return; - geometry_changed = !meta_rectangle_equal (&old_geometry, &xdg_surface_priv->geometry); + window_geometry = meta_wayland_xdg_surface_get_window_geometry (xdg_surface); + geometry_changed = !meta_rectangle_equal (&old_geometry, &window_geometry); if (geometry_changed || pending->has_acked_configure_serial) { - MetaRectangle window_geometry; - - window_geometry = meta_wayland_xdg_surface_get_window_geometry (xdg_surface); meta_window_wayland_finish_move_resize (window, window_geometry, pending); } else if (pending->dx != 0 || pending->dy != 0) @@ -821,7 +845,6 @@ wl_resource_post_error (surface->resource, XDG_WM_BASE_ERROR_INVALID_SURFACE_STATE, "Invalid min/max size"); - } } } @@ -940,6 +963,7 @@ surface_role_class = META_WAYLAND_SURFACE_ROLE_CLASS (klass); surface_role_class->apply_state = meta_wayland_xdg_toplevel_apply_state; + surface_role_class->post_apply_state = meta_wayland_xdg_toplevel_post_apply_state; surface_role_class->get_toplevel = meta_wayland_xdg_toplevel_get_toplevel; shell_surface_class = META_WAYLAND_SHELL_SURFACE_CLASS (klass); @@ -1089,13 +1113,11 @@ MetaWaylandXdgSurface *xdg_surface = META_WAYLAND_XDG_SURFACE (surface_role); MetaWaylandXdgSurfacePrivate *xdg_surface_priv = meta_wayland_xdg_surface_get_instance_private (xdg_surface); + MetaWaylandActorSurface *actor_surface = + META_WAYLAND_ACTOR_SURFACE (xdg_popup); MetaWaylandSurfaceRoleClass *surface_role_class; MetaWaylandSurface *surface = meta_wayland_surface_role_get_surface (surface_role); - MetaWindow *window; - MetaRectangle buffer_rect; - MetaWindow *parent_window; - MetaRectangle parent_buffer_rect; if (xdg_popup->setup.parent_surface) finish_popup_setup (xdg_popup); @@ -1103,7 +1125,7 @@ if (!surface->buffer_ref.buffer && xdg_surface_priv->first_buffer_attached) { meta_wayland_xdg_surface_reset (xdg_surface); - meta_wayland_surface_cache_pending_frame_callbacks (surface, pending); + meta_wayland_actor_surface_queue_frame_callbacks (actor_surface, pending); return; } @@ -1118,8 +1140,23 @@ "Can't commit buffer to dismissed popup"); return; } +} + +static void +meta_wayland_xdg_popup_post_apply_state (MetaWaylandSurfaceRole *surface_role, + MetaWaylandSurfaceState *pending) +{ + MetaWaylandXdgPopup *xdg_popup = META_WAYLAND_XDG_POPUP (surface_role); + MetaWaylandXdgSurface *xdg_surface = META_WAYLAND_XDG_SURFACE (surface_role); + MetaWaylandSurface *surface = + meta_wayland_surface_role_get_surface (surface_role); + MetaWaylandSurfaceRoleClass *surface_role_class = + META_WAYLAND_SURFACE_ROLE_CLASS (meta_wayland_xdg_popup_parent_class); + MetaWindow *window; + MetaWindow *parent_window; + MetaRectangle buffer_rect; + MetaRectangle parent_buffer_rect; - /* If the window disappeared the surface is not coming back. */ window = meta_wayland_surface_get_window (surface); if (!window) return; @@ -1130,6 +1167,8 @@ if (!surface->buffer_ref.buffer) return; + surface_role_class->post_apply_state (surface_role, pending); + if (pending->has_acked_configure_serial) { MetaRectangle window_geometry; @@ -1208,7 +1247,8 @@ } xdg_popup_send_configure (xdg_popup->resource, x, y, - configuration->width, configuration->height); + configuration->width / configuration->scale, + configuration->height / configuration->scale); meta_wayland_xdg_surface_send_configure (xdg_surface, configuration); } @@ -1326,6 +1366,7 @@ surface_role_class = META_WAYLAND_SURFACE_ROLE_CLASS (klass); surface_role_class->apply_state = meta_wayland_xdg_popup_apply_state; + surface_role_class->post_apply_state = meta_wayland_xdg_popup_post_apply_state; surface_role_class->get_toplevel = meta_wayland_xdg_popup_get_toplevel; shell_surface_class = META_WAYLAND_SHELL_SURFACE_CLASS (klass); @@ -1380,14 +1421,10 @@ static void xdg_surface_destructor (struct wl_resource *resource) { - MetaWaylandSurface *surface = surface_from_xdg_surface_resource (resource); MetaWaylandXdgSurface *xdg_surface = wl_resource_get_user_data (resource); MetaWaylandXdgSurfacePrivate *priv = meta_wayland_xdg_surface_get_instance_private (xdg_surface); - meta_wayland_compositor_destroy_frame_callbacks (surface->compositor, - surface); - priv->shell_client->surfaces = g_list_remove (priv->shell_client->surfaces, xdg_surface); @@ -1504,8 +1541,6 @@ MetaWaylandSurfaceState *pending) { MetaWaylandXdgSurface *xdg_surface = META_WAYLAND_XDG_SURFACE (surface_role); - MetaWaylandShellSurface *shell_surface = - META_WAYLAND_SHELL_SURFACE (xdg_surface); MetaWaylandXdgSurfacePrivate *priv = meta_wayland_xdg_surface_get_instance_private (xdg_surface); MetaWaylandSurface *surface = @@ -1526,8 +1561,17 @@ if (surface->buffer_ref.buffer) priv->first_buffer_attached = TRUE; - else - return; +} + +static void +meta_wayland_xdg_surface_post_apply_state (MetaWaylandSurfaceRole *surface_role, + MetaWaylandSurfaceState *pending) +{ + MetaWaylandXdgSurface *xdg_surface = META_WAYLAND_XDG_SURFACE (surface_role); + MetaWaylandXdgSurfacePrivate *priv = + meta_wayland_xdg_surface_get_instance_private (xdg_surface); + MetaWaylandShellSurface *shell_surface = + META_WAYLAND_SHELL_SURFACE (surface_role); if (pending->has_new_geometry) { @@ -1680,6 +1724,7 @@ surface_role_class = META_WAYLAND_SURFACE_ROLE_CLASS (klass); surface_role_class->apply_state = meta_wayland_xdg_surface_apply_state; + surface_role_class->post_apply_state = meta_wayland_xdg_surface_post_apply_state; surface_role_class->assigned = meta_wayland_xdg_surface_assigned; shell_surface_class = META_WAYLAND_SHELL_SURFACE_CLASS (klass); @@ -1802,13 +1847,40 @@ MetaWaylandSurface *surface = constructor->surface; struct wl_resource *xdg_wm_base_resource = constructor->shell_client->resource; struct wl_resource *xdg_surface_resource = constructor->resource; - MetaWaylandSurface *parent_surface = - surface_from_xdg_surface_resource (parent_resource); + MetaWaylandSurface *parent_surface; MetaWindow *parent_window; MetaWaylandXdgPositioner *xdg_positioner; MetaWaylandXdgPopup *xdg_popup; MetaWaylandXdgSurface *xdg_surface; + if (!parent_resource) + { + wl_resource_post_error (xdg_wm_base_resource, + XDG_WM_BASE_ERROR_INVALID_POPUP_PARENT, + "Parent surface is null but Mutter does not yet " + "support specifying parent surfaces via other " + "protocols"); + return; + } + + parent_surface = surface_from_xdg_surface_resource (parent_resource); + if (!parent_surface || !META_IS_WAYLAND_XDG_SURFACE (parent_surface->role)) + { + wl_resource_post_error (xdg_wm_base_resource, + XDG_WM_BASE_ERROR_INVALID_POPUP_PARENT, + "Invalid popup parent role"); + return; + } + + parent_window = meta_wayland_surface_get_window (parent_surface); + if (!parent_window) + { + wl_resource_post_error (xdg_wm_base_resource, + XDG_WM_BASE_ERROR_INVALID_POPUP_PARENT, + "Invalid popup parent window"); + return; + } + if (!meta_wayland_surface_assign_role (surface, META_TYPE_WAYLAND_XDG_POPUP, "shell-client", shell_client, @@ -1821,14 +1893,6 @@ return; } - if (!META_IS_WAYLAND_XDG_SURFACE (parent_surface->role)) - { - wl_resource_post_error (xdg_wm_base_resource, - XDG_WM_BASE_ERROR_INVALID_POPUP_PARENT, - "Invalid popup parent role"); - return; - } - xdg_popup = META_WAYLAND_XDG_POPUP (surface->role); xdg_popup->resource = wl_resource_create (client, @@ -1843,8 +1907,6 @@ xdg_surface = META_WAYLAND_XDG_SURFACE (xdg_popup); meta_wayland_xdg_surface_constructor_finalize (constructor, xdg_surface); - parent_window = meta_wayland_surface_get_window (parent_surface); - xdg_positioner = wl_resource_get_user_data (positioner_resource); xdg_popup->setup.placement_rule = meta_wayland_xdg_positioner_to_placement (xdg_positioner, parent_window); @@ -1982,8 +2044,10 @@ } if (configuration->has_size) { - parent_rect.width = configuration->width; - parent_rect.height = configuration->height; + parent_rect.width = + configuration->width / configuration->scale; + parent_rect.height = + configuration->height / configuration->scale; } } else if (xdg_positioner->has_parent_size) diff -Nru mutter-3.36.1/src/wayland/meta-window-wayland.c mutter-3.36.9/src/wayland/meta-window-wayland.c --- mutter-3.36.1/src/wayland/meta-window-wayland.c 2020-03-30 19:29:39.349884000 +0000 +++ mutter-3.36.9/src/wayland/meta-window-wayland.c 2021-03-15 23:07:33.336499000 +0000 @@ -59,6 +59,8 @@ int last_sent_height; int last_sent_rel_x; int last_sent_rel_y; + int last_sent_geometry_scale; + MetaGravity last_sent_gravity; gboolean has_been_shown; }; @@ -191,8 +193,9 @@ wl_window->last_sent_y, wl_window->last_sent_width, wl_window->last_sent_height, + wl_window->last_sent_geometry_scale, META_MOVE_RESIZE_STATE_CHANGED, - META_GRAVITY_NONE); + wl_window->last_sent_gravity); meta_window_wayland_configure (wl_window, configuration); } @@ -270,8 +273,8 @@ } else { - configured_width = constrained_rect.width / geometry_scale; - configured_height = constrained_rect.height / geometry_scale; + configured_width = constrained_rect.width; + configured_height = constrained_rect.height; } /* For wayland clients, the size is completely determined by the client, @@ -333,7 +336,8 @@ meta_wayland_window_configuration_new_relative (rel_x, rel_y, configured_width, - configured_height); + configured_height, + geometry_scale); meta_window_wayland_configure (wl_window, configuration); wl_window->last_sent_rel_x = rel_x; @@ -385,6 +389,7 @@ configured_y, configured_width, configured_height, + geometry_scale, flags, gravity); meta_window_wayland_configure (wl_window, configuration); @@ -400,6 +405,8 @@ wl_window->last_sent_y = configured_y; wl_window->last_sent_width = configured_width; wl_window->last_sent_height = configured_height; + wl_window->last_sent_geometry_scale = geometry_scale; + wl_window->last_sent_gravity = gravity; if (can_move_now) { @@ -711,6 +718,12 @@ return !wl_window->has_been_shown; } +static gboolean +meta_window_wayland_is_focus_async (MetaWindow *window) +{ + return FALSE; +} + static MetaStackLayer meta_window_wayland_calculate_layer (MetaWindow *window) { @@ -767,6 +780,7 @@ window_class->calculate_layer = meta_window_wayland_calculate_layer; window_class->map = meta_window_wayland_map; window_class->unmap = meta_window_wayland_unmap; + window_class->is_focus_async = meta_window_wayland_is_focus_async; } MetaWindow * @@ -877,6 +891,38 @@ return get_window_geometry_scale_for_logical_monitor (window->monitor); } +static void +calculate_offset (MetaWaylandWindowConfiguration *configuration, + MetaRectangle *geometry, + MetaRectangle *rect) +{ + int offset_x; + int offset_y; + + rect->x = configuration->x; + rect->y = configuration->y; + + offset_x = configuration->width - geometry->width; + offset_y = configuration->height - geometry->height; + switch (configuration->gravity) + { + case META_GRAVITY_SOUTH: + case META_GRAVITY_SOUTH_WEST: + rect->y += offset_y; + break; + case META_GRAVITY_EAST: + case META_GRAVITY_NORTH_EAST: + rect->x += offset_x; + break; + case META_GRAVITY_SOUTH_EAST: + rect->x += offset_x; + rect->y += offset_y; + break; + default: + break; + } +} + /** * meta_window_move_resize_wayland: * @@ -939,8 +985,7 @@ } else { - rect.x = acked_configuration->x; - rect.y = acked_configuration->y; + calculate_offset (acked_configuration, &new_geom, &rect); } } else @@ -951,19 +996,16 @@ rect.x += dx; rect.y += dy; - - if (rect.x != window->rect.x || rect.y != window->rect.y) - flags |= META_MOVE_RESIZE_MOVE_ACTION; } else { if (acked_configuration) - { - rect.x = acked_configuration->x; - rect.y = acked_configuration->y; - } + calculate_offset (acked_configuration, &new_geom, &rect); } + if (rect.x != window->rect.x || rect.y != window->rect.y) + flags |= META_MOVE_RESIZE_MOVE_ACTION; + if (wl_window->has_pending_state_change && acked_configuration) { flags |= META_MOVE_RESIZE_WAYLAND_STATE_CHANGED; diff -Nru mutter-3.36.1/src/wayland/meta-xwayland-dnd.c mutter-3.36.9/src/wayland/meta-xwayland-dnd.c --- mutter-3.36.1/src/wayland/meta-xwayland-dnd.c 2020-03-30 19:29:39.349884000 +0000 +++ mutter-3.36.9/src/wayland/meta-xwayland-dnd.c 2021-03-15 23:07:33.336499000 +0000 @@ -145,6 +145,8 @@ gchar **p; struct wl_array *source_mime_types; + meta_x11_error_trap_push (x11_display); + data_source = compositor->seat->data_device.dnd_data_source; xev.xclient.type = ClientMessage; xev.xclient.message_type = xdnd_atoms[ATOM_DND_ENTER]; @@ -189,6 +191,9 @@ } XSendEvent (xdisplay, dest, False, NoEventMask, &xev); + + if (meta_x11_error_trap_pop_with_return (x11_display) != Success) + g_critical ("Error sending XdndEnter"); } static void @@ -205,7 +210,9 @@ xev.xclient.window = dest; xev.xclient.data.l[0] = x11_display->selection.xwindow; + meta_x11_error_trap_push (x11_display); XSendEvent (xdisplay, dest, False, NoEventMask, &xev); + meta_x11_error_trap_pop (x11_display); } static void @@ -223,7 +230,7 @@ XEvent xev = { 0 }; user_action = meta_wayland_data_source_get_user_action (source); - actions = meta_wayland_data_source_get_actions (source); + meta_wayland_data_source_get_actions (source, &actions); if (user_action & actions) action = user_action; @@ -241,7 +248,11 @@ xev.xclient.data.l[3] = time; xev.xclient.data.l[4] = action_to_atom (action); + meta_x11_error_trap_push (x11_display); XSendEvent (xdisplay, dest, False, NoEventMask, &xev); + + if (meta_x11_error_trap_pop_with_return (x11_display) != Success) + g_critical ("Error sending XdndPosition"); } static void @@ -261,7 +272,11 @@ xev.xclient.data.l[0] = x11_display->selection.xwindow; xev.xclient.data.l[2] = time; + meta_x11_error_trap_push (x11_display); XSendEvent (xdisplay, dest, False, NoEventMask, &xev); + + if (meta_x11_error_trap_pop_with_return (x11_display) != Success) + g_critical ("Error sending XdndDrop"); } static void @@ -289,7 +304,11 @@ xev.xclient.data.l[2] = action_to_atom (action); } + meta_x11_error_trap_push (x11_display); XSendEvent (xdisplay, dest, False, NoEventMask, &xev); + + if (meta_x11_error_trap_pop_with_return (x11_display) != Success) + g_critical ("Error sending XdndFinished"); } static void @@ -297,6 +316,7 @@ Window dest, uint32_t action) { + MetaX11Display *x11_display = meta_get_display ()->x11_display; Display *xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()); XEvent xev = { 0 }; @@ -312,18 +332,30 @@ if (xev.xclient.data.l[4]) xev.xclient.data.l[1] |= 1 << 0; /* Bit 1: dest accepts the drop */ + meta_x11_error_trap_push (x11_display); XSendEvent (xdisplay, dest, False, NoEventMask, &xev); + + if (meta_x11_error_trap_pop_with_return (x11_display) != Success) + g_critical ("Error sending Xdndstatus"); } static void -meta_xwayland_end_dnd_grab (MetaWaylandDataDevice *data_device) +meta_xwayland_end_dnd_grab (MetaWaylandDataDevice *data_device, + gboolean success) { Display *xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()); MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default (); MetaXWaylandManager *manager = &compositor->xwayland_manager; + MetaWaylandDragGrab *drag_grab = compositor->seat->data_device.current_grab; MetaXWaylandDnd *dnd = manager->dnd; - meta_wayland_data_device_end_drag (data_device); + if (drag_grab) + { + if (!success && dnd->source) + meta_wayland_data_source_set_current_offer (dnd->source, NULL); + + meta_wayland_data_device_end_drag (data_device); + } XMoveResizeWindow (xdisplay, dnd->dnd_window, -1, -1, 1, 1); XUnmapWindow (xdisplay, dnd->dnd_window); @@ -343,6 +375,7 @@ } g_output_stream_close (stream, NULL, NULL); + g_object_unref (stream); } static void @@ -691,7 +724,7 @@ (!meta_wayland_drag_grab_get_focus ((MetaWaylandDragGrab *) grab) || meta_wayland_data_source_get_current_action (data_source) == WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE)) - meta_xwayland_end_dnd_grab (&seat->data_device); + meta_xwayland_end_dnd_grab (&seat->data_device, FALSE); } static const MetaWaylandPointerGrabInterface drag_xgrab_interface = { @@ -834,7 +867,7 @@ { dnd->client_message_timestamp = event->data.l[2]; meta_wayland_surface_drag_dest_drop (drag_focus); - meta_xwayland_end_dnd_grab (&seat->data_device); + meta_xwayland_end_dnd_grab (&seat->data_device, TRUE); return TRUE; } } @@ -873,7 +906,8 @@ } else if (event->owner == None) { - meta_xwayland_end_dnd_grab (data_device); + meta_xwayland_end_dnd_grab (data_device, FALSE); + g_clear_object (&dnd->source); } return FALSE; diff -Nru mutter-3.36.1/src/x11/group.c mutter-3.36.9/src/x11/group.c --- mutter-3.36.1/src/x11/group.c 2020-03-30 19:29:39.352883800 +0000 +++ mutter-3.36.9/src/x11/group.c 2021-03-15 23:07:33.339498800 +0000 @@ -41,7 +41,7 @@ meta_group_new (MetaX11Display *x11_display, Window group_leader) { - MetaGroup *group; + g_autofree MetaGroup *group = NULL; #define N_INITIAL_PROPS 3 Atom initial_props[N_INITIAL_PROPS]; int i; @@ -91,7 +91,7 @@ "Created new group with leader 0x%lx\n", group->group_leader); - return group; + return g_steal_pointer (&group); } static void diff -Nru mutter-3.36.1/src/x11/meta-startup-notification-x11.c mutter-3.36.9/src/x11/meta-startup-notification-x11.c --- mutter-3.36.1/src/x11/meta-startup-notification-x11.c 2020-03-30 19:29:39.352883800 +0000 +++ mutter-3.36.9/src/x11/meta-startup-notification-x11.c 2021-03-15 23:07:33.340499000 +0000 @@ -355,7 +355,7 @@ (gpointer *) &func); } - if (func) + if (func && application_id) func (sn_launcher, application_id); g_module_close (self); diff -Nru mutter-3.36.1/src/x11/meta-x11-display-private.h mutter-3.36.9/src/x11/meta-x11-display-private.h --- mutter-3.36.1/src/x11/meta-x11-display-private.h 2020-03-30 19:29:39.353883700 +0000 +++ mutter-3.36.9/src/x11/meta-x11-display-private.h 2021-03-15 23:07:33.340499000 +0000 @@ -127,6 +127,7 @@ struct { Window xwindow; + guint timeout_id; MetaSelectionSource *owners[META_N_SELECTION_TYPES]; GCancellable *cancellables[META_N_SELECTION_TYPES]; diff -Nru mutter-3.36.1/src/x11/meta-x11-selection.c mutter-3.36.9/src/x11/meta-x11-selection.c --- mutter-3.36.1/src/x11/meta-x11-selection.c 2020-03-30 19:29:39.354884000 +0000 +++ mutter-3.36.9/src/x11/meta-x11-selection.c 2021-03-15 23:07:33.341498900 +0000 @@ -23,6 +23,8 @@ #include +#include "core/meta-selection-private.h" +#include "meta/meta-selection-source-memory.h" #include "x11/meta-selection-source-x11-private.h" #include "x11/meta-x11-selection-output-stream-private.h" #include "x11/meta-x11-selection-private.h" @@ -77,18 +79,49 @@ mimetypes_to_bytes (GList *mimetypes, Display *xdisplay) { - gint i = 0, len = g_list_length (mimetypes) + 2; - Atom *atoms = g_new0 (Atom, len); + GArray *atoms = g_array_new (FALSE, FALSE, sizeof (Atom)); GList *l; + char *mimetype; + Atom atom; + gboolean utf8_string_found = FALSE, utf8_string_mimetype_found = FALSE; + gboolean string_found = FALSE, string_mimetype_found = FALSE; + GBytes *bytes; for (l = mimetypes; l; l = l->next) - atoms[i++] = XInternAtom (xdisplay, l->data, False); + { + mimetype = l->data; + atom = XInternAtom (xdisplay, mimetype, False); + g_array_append_val (atoms, atom); + utf8_string_mimetype_found |= strcmp (mimetype, UTF8_STRING_MIMETYPE) == 0; + utf8_string_found |= strcmp (mimetype, "UTF8_STRING") == 0; + string_mimetype_found |= strcmp (mimetype, STRING_MIMETYPE) == 0; + string_found |= strcmp (mimetype, "STRING") == 0; + } + + /* Some X11 clients can only handle STRING/UTF8_STRING but not the + * corresponding mimetypes. */ + if (utf8_string_mimetype_found && !utf8_string_found) + { + atom = XInternAtom (xdisplay, "UTF8_STRING", False); + g_array_append_val (atoms, atom); + } + + if (string_mimetype_found && !string_found) + { + atom = XInternAtom (xdisplay, "STRING", False); + g_array_append_val (atoms, atom); + } + + atom = XInternAtom (xdisplay, "TARGETS", False); + g_array_append_val (atoms, atom); - atoms[i++] = XInternAtom (xdisplay, "TARGETS", False); - atoms[i++] = XInternAtom (xdisplay, "TIMESTAMP", False); - g_assert (i == len); + atom = XInternAtom (xdisplay, "TIMESTAMP", False); + g_array_append_val (atoms, atom); - return g_bytes_new_take (atoms, len * sizeof (Atom)); + bytes = g_bytes_new_take (atoms->data, atoms->len * sizeof (Atom)); + g_array_free (atoms, FALSE); + + return bytes; } static void @@ -296,8 +329,8 @@ source = meta_selection_source_x11_new_finish (res, &error); if (source) { - meta_selection_set_owner (selection, selection_type, source); g_set_object (&x11_display->selection.owners[selection_type], source); + meta_selection_set_owner (selection, selection_type, source); g_object_unref (source); } else if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) @@ -310,6 +343,22 @@ } static gboolean +unset_clipboard_owner (gpointer data) +{ + MetaDisplay *display = meta_get_display (); + MetaSelection *selection = meta_display_get_selection (display); + MetaX11Display *x11_display = meta_display_get_x11_display (display); + + meta_selection_unset_owner (selection, META_SELECTION_CLIPBOARD, + x11_display->selection.owners[META_SELECTION_CLIPBOARD]); + g_clear_object (&x11_display->selection.owners[META_SELECTION_CLIPBOARD]); + + x11_display->selection.timeout_id = 0; + + return G_SOURCE_REMOVE; +} + +static gboolean meta_x11_selection_handle_xfixes_selection_notify (MetaX11Display *x11_display, XEvent *xevent) { @@ -323,6 +372,9 @@ selection = meta_display_get_selection (meta_get_display ()); + if (selection_type == META_SELECTION_CLIPBOARD) + g_clear_handle_id (&x11_display->selection.timeout_id, g_source_remove); + if (x11_display->selection.cancellables[selection_type]) { g_cancellable_cancel (x11_display->selection.cancellables[selection_type]); @@ -331,16 +383,40 @@ x11_display->selection.cancellables[selection_type] = g_cancellable_new (); - if (event->owner == None) + if (event->owner == None && x11_display->selection.owners[selection_type]) { - if (x11_display->selection.owners[selection_type]) + if (event->subtype == XFixesSetSelectionOwnerNotify) + { + MetaSelectionSource *source; + + /* Replace with an empty owner */ + source = g_object_new (META_TYPE_SELECTION_SOURCE_MEMORY, NULL); + g_set_object (&x11_display->selection.owners[selection_type], source); + meta_selection_set_owner (selection, selection_type, source); + g_object_unref (source); + } + else if (event->subtype == XFixesSelectionWindowDestroyNotify && + selection_type == META_SELECTION_CLIPBOARD) + { + /* Selection window might have gotten destroyed as part of application + * shutdown. Trigger restoring clipboard, but wait a bit, because some + * clients, like wine, destroy the old window immediately before a new + * selection. Restoring the clipboard in this case would overwrite the + * new selection, so this will be cancelled when a new selection + * arrives. */ + x11_display->selection.timeout_id = g_timeout_add (10, + unset_clipboard_owner, + NULL); + } + else { /* An X client went away, clear the selection */ meta_selection_unset_owner (selection, selection_type, x11_display->selection.owners[selection_type]); + g_clear_object (&x11_display->selection.owners[selection_type]); } } - else if (event->owner != x11_display->selection.xwindow) + else if (event->owner != None && event->owner != x11_display->selection.xwindow) { SourceNewData *data; @@ -374,14 +450,13 @@ } static void -owner_changed_cb (MetaSelection *selection, - MetaSelectionType selection_type, - MetaSelectionSource *new_owner, - MetaX11Display *x11_display) +notify_selection_owner (MetaX11Display *x11_display, + MetaSelectionType selection_type, + MetaSelectionSource *new_owner) { Display *xdisplay = x11_display->xdisplay; - if (new_owner && !META_IS_SELECTION_SOURCE_X11 (new_owner)) + if (new_owner && new_owner != x11_display->selection.owners[selection_type]) { if (x11_display->selection.cancellables[selection_type]) { @@ -404,11 +479,13 @@ { XSetWindowAttributes attributes = { 0 }; MetaDisplay *display = meta_get_display (); + MetaSelection *selection; guint mask, i; attributes.event_mask = PropertyChangeMask | SubstructureNotifyMask; attributes.override_redirect = True; + x11_display->selection.timeout_id = 0; x11_display->selection.xwindow = XCreateWindow (x11_display->xdisplay, x11_display->xroot, @@ -424,18 +501,24 @@ XFixesSelectionWindowDestroyNotifyMask | XFixesSelectionClientCloseNotifyMask; + selection = meta_display_get_selection (display); + for (i = 0; i < META_N_SELECTION_TYPES; i++) { + MetaSelectionSource *owner; + XFixesSelectSelectionInput (x11_display->xdisplay, x11_display->selection.xwindow, selection_to_atom (i, x11_display->xdisplay), mask); + owner = meta_selection_get_current_owner (selection, i); + notify_selection_owner (x11_display, i, owner); } - g_signal_connect (meta_display_get_selection (display), - "owner-changed", - G_CALLBACK (owner_changed_cb), - x11_display); + g_signal_connect_swapped (selection, + "owner-changed", + G_CALLBACK (notify_selection_owner), + x11_display); } void @@ -445,7 +528,7 @@ guint i; g_signal_handlers_disconnect_by_func (meta_display_get_selection (display), - owner_changed_cb, + notify_selection_owner, x11_display); for (i = 0; i < META_N_SELECTION_TYPES; i++) @@ -463,4 +546,6 @@ XDestroyWindow (x11_display->xdisplay, x11_display->selection.xwindow); x11_display->selection.xwindow = None; } + + g_clear_handle_id (&x11_display->selection.timeout_id, g_source_remove); } diff -Nru mutter-3.36.1/src/x11/meta-x11-selection-output-stream.c mutter-3.36.9/src/x11/meta-x11-selection-output-stream.c --- mutter-3.36.1/src/x11/meta-x11-selection-output-stream.c 2020-03-30 19:29:39.353883700 +0000 +++ mutter-3.36.9/src/x11/meta-x11-selection-output-stream.c 2021-03-15 23:07:33.341498900 +0000 @@ -60,6 +60,8 @@ meta_x11_selection_output_stream, G_TYPE_OUTPUT_STREAM); +static size_t get_element_size (int format); + static void meta_x11_selection_output_stream_notify_selection (MetaX11SelectionOutputStream *stream) { @@ -97,6 +99,9 @@ if (priv->delete_pending) return FALSE; + if (!g_output_stream_is_closing (G_OUTPUT_STREAM (stream)) && + priv->data->len < get_element_size (priv->format)) + return FALSE; return TRUE; } @@ -110,7 +115,7 @@ if (size <= 0) size = XMaxRequestSize (display->xdisplay); - return size - 100; + return (size - 100) * 4; } static gboolean @@ -120,7 +125,12 @@ meta_x11_selection_output_stream_get_instance_private (stream); if (priv->data->len == 0) - return FALSE; + { + if (priv->incr) + return g_output_stream_is_closing (G_OUTPUT_STREAM (stream)); + else + return FALSE; + } if (g_output_stream_is_closing (G_OUTPUT_STREAM (stream))) return TRUE; @@ -193,7 +203,8 @@ MetaX11SelectionOutputStreamPrivate *priv = meta_x11_selection_output_stream_get_instance_private (stream); Display *xdisplay; - size_t element_size, n_elements; + size_t element_size, n_elements, max_size; + gboolean first_chunk = FALSE; int error_code; g_assert (!priv->delete_pending); @@ -207,8 +218,12 @@ element_size = get_element_size (priv->format); n_elements = priv->data->len / element_size; + max_size = get_max_request_size (priv->x11_display); - if (!g_output_stream_is_closing (G_OUTPUT_STREAM (stream))) + if (!priv->incr) + first_chunk = TRUE; + + if (!priv->incr && priv->data->len > max_size) { XWindowAttributes attrs; @@ -224,14 +239,22 @@ XChangeProperty (xdisplay, priv->xwindow, priv->xproperty, - XInternAtom (priv->x11_display->xdisplay, "INCR", True), + XInternAtom (priv->x11_display->xdisplay, "INCR", False), 32, PropModeReplace, (guchar *) &(long) { n_elements }, 1); + priv->delete_pending = TRUE; } else { + size_t copy_n_elements; + + if (priv->incr && priv->data->len > 0) + priv->delete_pending = TRUE; + + copy_n_elements = MIN (n_elements, max_size / element_size); + XChangeProperty (xdisplay, priv->xwindow, priv->xproperty, @@ -239,15 +262,13 @@ priv->format, PropModeReplace, priv->data->data, - n_elements); - g_byte_array_remove_range (priv->data, 0, n_elements * element_size); - if (priv->data->len < element_size) - priv->flush_requested = FALSE; + copy_n_elements); + g_byte_array_remove_range (priv->data, 0, copy_n_elements * element_size); } - meta_x11_selection_output_stream_notify_selection (stream); + if (first_chunk) + meta_x11_selection_output_stream_notify_selection (stream); - priv->delete_pending = TRUE; g_cond_broadcast (&priv->cond); g_mutex_unlock (&priv->mutex); @@ -257,19 +278,26 @@ { char error_str[100]; - XGetErrorText (xdisplay, error_code, error_str, sizeof (error_str)); - g_task_return_new_error (priv->pending_task, - G_IO_ERROR, - G_IO_ERROR_BROKEN_PIPE, - "Failed to flush selection output stream: %s", - error_str); - g_clear_object (&priv->pending_task); + priv->flush_requested = FALSE; + priv->delete_pending = FALSE; priv->pipe_error = TRUE; + + if (priv->pending_task) + { + XGetErrorText (xdisplay, error_code, error_str, sizeof (error_str)); + g_task_return_new_error (priv->pending_task, + G_IO_ERROR, + G_IO_ERROR_BROKEN_PIPE, + "Failed to flush selection output stream: %s", + error_str); + g_clear_object (&priv->pending_task); + } } - else if (priv->pending_task) + else if (priv->pending_task && priv->data->len == 0 && !priv->delete_pending) { size_t result; + priv->flush_requested = FALSE; result = GPOINTER_TO_SIZE (g_task_get_task_data (priv->pending_task)); g_task_return_int (priv->pending_task, result); g_clear_object (&priv->pending_task); @@ -281,12 +309,17 @@ { MetaX11SelectionOutputStream *stream = META_X11_SELECTION_OUTPUT_STREAM (data); + MetaX11SelectionOutputStreamPrivate *priv = + meta_x11_selection_output_stream_get_instance_private (stream); if (meta_x11_selection_output_stream_needs_flush (stream) && meta_x11_selection_output_stream_can_flush (stream)) meta_x11_selection_output_stream_perform_flush (stream); - return G_SOURCE_REMOVE; + if (priv->delete_pending || priv->data->len > 0) + return G_SOURCE_CONTINUE; + else + return G_SOURCE_REMOVE; } static gssize @@ -354,16 +387,11 @@ g_object_unref (task); return; } - else if (!meta_x11_selection_output_stream_can_flush (stream)) - { - g_assert (priv->pending_task == NULL); - priv->pending_task = task; - g_task_set_task_data (task, GSIZE_TO_POINTER (count), NULL); - return; - } else { - meta_x11_selection_output_stream_perform_flush (stream); + if (meta_x11_selection_output_stream_can_flush (stream)) + meta_x11_selection_output_stream_perform_flush (stream); + g_task_return_int (task, count); g_object_unref (task); return; @@ -391,7 +419,7 @@ g_mutex_lock (&priv->mutex); - if (priv->data->len >= get_element_size (priv->format)) + if (priv->data->len > 0) priv->flush_requested = TRUE; needs_flush = meta_x11_selection_output_stream_needs_flush_unlocked (stream); @@ -466,10 +494,9 @@ } } + g_assert (priv->pending_task == NULL); + priv->pending_task = task; meta_x11_selection_output_stream_perform_flush (stream); - g_task_return_boolean (task, TRUE); - g_object_unref (task); - return; } static gboolean diff -Nru mutter-3.36.1/src/x11/window-props.c mutter-3.36.9/src/x11/window-props.c --- mutter-3.36.1/src/x11/window-props.c 2020-03-30 19:29:39.355883800 +0000 +++ mutter-3.36.9/src/x11/window-props.c 2021-03-15 23:07:33.342498800 +0000 @@ -1099,13 +1099,19 @@ } } +#define FLAG_IS_ON(hints,flag) \ + (((hints)->flags & (flag)) != 0) + +#define FLAG_IS_OFF(hints,flag) \ + (((hints)->flags & (flag)) == 0) + #define FLAG_TOGGLED_ON(old,new,flag) \ - (((old)->flags & (flag)) == 0 && \ - ((new)->flags & (flag)) != 0) + (FLAG_IS_OFF(old,flag) && \ + FLAG_IS_ON(new,flag)) #define FLAG_TOGGLED_OFF(old,new,flag) \ - (((old)->flags & (flag)) != 0 && \ - ((new)->flags & (flag)) == 0) + (FLAG_IS_ON(old,flag) && \ + FLAG_IS_OFF(new,flag)) #define FLAG_CHANGED(old,new,flag) \ (FLAG_TOGGLED_ON(old,new,flag) || FLAG_TOGGLED_OFF(old,new,flag)) @@ -1159,6 +1165,86 @@ old->win_gravity, new->win_gravity); } +static gboolean +hints_have_changed (const XSizeHints *old, + const XSizeHints *new) +{ + /* 1. Check if the relevant values have changed if the flag is set. */ + + if (FLAG_TOGGLED_ON (old, new, USPosition) || + (FLAG_IS_ON (new, USPosition) && + (old->x != new->x || + old->y != new->y))) + return TRUE; + + if (FLAG_TOGGLED_ON (old, new, USSize) || + (FLAG_IS_ON (new, USSize) && + (old->width != new->width || + old->height != new->height))) + return TRUE; + + if (FLAG_TOGGLED_ON (old, new, PPosition) || + (FLAG_IS_ON (new, PPosition) && + (old->x != new->x || + old->y != new->y))) + return TRUE; + + if (FLAG_TOGGLED_ON (old, new, PSize) || + (FLAG_IS_ON (new, PSize) && + (old->width != new->width || + old->height != new->height))) + return TRUE; + + if (FLAG_TOGGLED_ON (old, new, PMinSize) || + (FLAG_IS_ON (new, PMinSize) && + (old->min_width != new->min_width || + old->min_height != new->min_height))) + return TRUE; + + if (FLAG_TOGGLED_ON (old, new, PMaxSize) || + (FLAG_IS_ON (new, PMaxSize) && + (old->max_width != new->max_width || + old->max_height != new->max_height))) + return TRUE; + + if (FLAG_TOGGLED_ON (old, new, PResizeInc) || + (FLAG_IS_ON (new, PResizeInc) && + (old->width_inc != new->width_inc || + old->height_inc != new->height_inc))) + return TRUE; + + if (FLAG_TOGGLED_ON (old, new, PAspect) || + (FLAG_IS_ON (new, PAspect) && + (old->min_aspect.x != new->min_aspect.x || + old->min_aspect.y != new->min_aspect.y || + old->max_aspect.x != new->max_aspect.x || + old->max_aspect.y != new->max_aspect.y))) + return TRUE; + + if (FLAG_TOGGLED_ON (old, new, PBaseSize) || + (FLAG_IS_ON (new, PBaseSize) && + (old->base_width != new->base_width || + old->base_height != new->base_height))) + return TRUE; + + if (FLAG_TOGGLED_ON (old, new, PWinGravity) || + (FLAG_IS_ON (new, PWinGravity) && + (old->win_gravity != new->win_gravity))) + return TRUE; + + /* 2. Check if the flags have been unset. */ + return FLAG_TOGGLED_OFF (old, new, USPosition) || + FLAG_TOGGLED_OFF (old, new, USSize) || + FLAG_TOGGLED_OFF (old, new, PPosition) || + FLAG_TOGGLED_OFF (old, new, PSize) || + FLAG_TOGGLED_OFF (old, new, PMinSize) || + FLAG_TOGGLED_OFF (old, new, PMaxSize) || + FLAG_TOGGLED_OFF (old, new, PResizeInc) || + FLAG_TOGGLED_OFF (old, new, PAspect) || + FLAG_TOGGLED_OFF (old, new, PBaseSize) || + FLAG_TOGGLED_OFF (old, new, PWinGravity); +} + void meta_set_normal_hints (MetaWindow *window, XSizeHints *hints) @@ -1509,6 +1595,7 @@ if (value->type != META_PROP_VALUE_INVALID) { XSizeHints old_hints; + gboolean hints_have_differences; meta_topic (META_DEBUG_GEOMETRY, "Updating WM_NORMAL_HINTS for %s\n", window->desc); @@ -1516,12 +1603,16 @@ meta_set_normal_hints (window, value->v.size_hints.hints); - spew_size_hints_differences (&old_hints, &window->size_hints); - - meta_window_recalc_features (window); + hints_have_differences = hints_have_changed (&old_hints, + &window->size_hints); + if (hints_have_differences) + { + spew_size_hints_differences (&old_hints, &window->size_hints); + meta_window_recalc_features (window); - if (!initial) - meta_window_queue(window, META_QUEUE_MOVE_RESIZE); + if (!initial) + meta_window_queue (window, META_QUEUE_MOVE_RESIZE); + } } } diff -Nru mutter-3.36.1/src/x11/window-x11.c mutter-3.36.9/src/x11/window-x11.c --- mutter-3.36.1/src/x11/window-x11.c 2020-03-30 19:29:39.356883800 +0000 +++ mutter-3.36.9/src/x11/window-x11.c 2021-03-15 23:07:33.343498700 +0000 @@ -2027,6 +2027,16 @@ return FALSE; } +static gboolean +meta_window_x11_is_focus_async (MetaWindow *window) +{ + MetaWindowX11 *window_x11 = META_WINDOW_X11 (window); + MetaWindowX11Private *priv = + meta_window_x11_get_instance_private (window_x11); + + return !window->input && priv->wm_take_focus; +} + static void meta_window_x11_class_init (MetaWindowX11Class *klass) { @@ -2057,6 +2067,7 @@ window_class->calculate_layer = meta_window_x11_calculate_layer; window_class->map = meta_window_x11_map; window_class->unmap = meta_window_x11_unmap; + window_class->is_focus_async = meta_window_x11_is_focus_async; klass->freeze_commits = meta_window_x11_impl_freeze_commits; klass->thaw_commits = meta_window_x11_impl_thaw_commits;