diff -Nru mutter-44.0/clutter/clutter/clutter-backend.c mutter-44.1/clutter/clutter/clutter-backend.c --- mutter-44.0/clutter/clutter/clutter-backend.c 2023-03-19 10:55:05.000000000 +0000 +++ mutter-44.1/clutter/clutter/clutter-backend.c 2023-04-25 16:16:17.000000000 +0000 @@ -688,7 +688,7 @@ /** * clutter_backend_set_input_method: * @backend: the #ClutterBackend - * @method: the input method + * @method: (nullable): the input method * * Sets the input method to be used by Clutter **/ @@ -696,6 +696,12 @@ clutter_backend_set_input_method (ClutterBackend *backend, ClutterInputMethod *method) { + if (backend->input_method == method) + return; + + if (backend->input_method) + clutter_input_method_focus_out (backend->input_method); + g_set_object (&backend->input_method, method); } diff -Nru mutter-44.0/clutter/clutter/clutter-frame.c mutter-44.1/clutter/clutter/clutter-frame.c --- mutter-44.0/clutter/clutter/clutter-frame.c 2023-03-19 10:55:05.000000000 +0000 +++ mutter-44.1/clutter/clutter/clutter-frame.c 2023-04-25 16:16:17.000000000 +0000 @@ -75,6 +75,21 @@ } } +gboolean +clutter_frame_get_min_render_time_allowed (ClutterFrame *frame, + int64_t *min_render_time_allowed_us) +{ + if (frame->has_target_presentation_time) + { + *min_render_time_allowed_us = frame->min_render_time_allowed_us; + return TRUE; + } + else + { + return FALSE; + } +} + ClutterFrameResult clutter_frame_get_result (ClutterFrame *frame) { diff -Nru mutter-44.0/clutter/clutter/clutter-frame-clock.c mutter-44.1/clutter/clutter/clutter-frame-clock.c --- mutter-44.0/clutter/clutter/clutter-frame-clock.c 2023-03-19 10:55:05.000000000 +0000 +++ mutter-44.1/clutter/clutter/clutter-frame-clock.c 2023-04-25 16:16:17.000000000 +0000 @@ -79,6 +79,7 @@ gboolean is_next_presentation_time_valid; int64_t next_presentation_time_us; + int64_t min_render_time_allowed_us; /* Buffer must be submitted to KMS and GPU rendering must be finished * this amount of time before the next presentation time. @@ -466,7 +467,8 @@ static void calculate_next_update_time_us (ClutterFrameClock *frame_clock, int64_t *out_next_update_time_us, - int64_t *out_next_presentation_time_us) + int64_t *out_next_presentation_time_us, + int64_t *out_min_render_time_allowed_us) { int64_t last_presentation_time_us; int64_t now_us; @@ -489,6 +491,7 @@ now_us; *out_next_presentation_time_us = 0; + *out_min_render_time_allowed_us = 0; return; } @@ -613,6 +616,7 @@ *out_next_update_time_us = next_update_time_us; *out_next_presentation_time_us = next_presentation_time_us; + *out_min_render_time_allowed_us = min_render_time_allowed_us; } void @@ -704,7 +708,8 @@ case CLUTTER_FRAME_CLOCK_STATE_IDLE: calculate_next_update_time_us (frame_clock, &next_update_time_us, - &frame_clock->next_presentation_time_us); + &frame_clock->next_presentation_time_us, + &frame_clock->min_render_time_allowed_us); frame_clock->is_next_presentation_time_valid = (frame_clock->next_presentation_time_us != 0); break; @@ -775,6 +780,7 @@ frame->frame_count = frame_count; frame->has_target_presentation_time = frame_clock->is_next_presentation_time_valid; frame->target_presentation_time_us = frame_clock->next_presentation_time_us; + frame->min_render_time_allowed_us = frame_clock->min_render_time_allowed_us; COGL_TRACE_BEGIN (ClutterFrameClockEvents, "Frame Clock (before frame)"); if (iface->before_frame) diff -Nru mutter-44.0/clutter/clutter/clutter-frame.h mutter-44.1/clutter/clutter/clutter-frame.h --- mutter-44.0/clutter/clutter/clutter-frame.h 2023-03-19 10:55:05.000000000 +0000 +++ mutter-44.1/clutter/clutter/clutter-frame.h 2023-04-25 16:16:17.000000000 +0000 @@ -45,6 +45,10 @@ int64_t *target_presentation_time_us); CLUTTER_EXPORT +gboolean clutter_frame_get_min_render_time_allowed (ClutterFrame *frame, + int64_t *min_render_time_allowed_us); + +CLUTTER_EXPORT void clutter_frame_set_result (ClutterFrame *frame, ClutterFrameResult result); diff -Nru mutter-44.0/clutter/clutter/clutter-frame-private.h mutter-44.1/clutter/clutter/clutter-frame-private.h --- mutter-44.0/clutter/clutter/clutter-frame-private.h 2023-03-19 10:55:05.000000000 +0000 +++ mutter-44.1/clutter/clutter/clutter-frame-private.h 2023-04-25 16:16:17.000000000 +0000 @@ -31,6 +31,7 @@ gboolean has_target_presentation_time; int64_t target_presentation_time_us; + int64_t min_render_time_allowed_us; gboolean has_result; ClutterFrameResult result; diff -Nru mutter-44.0/clutter/clutter/clutter-paint-context.c mutter-44.1/clutter/clutter/clutter-paint-context.c --- mutter-44.0/clutter/clutter/clutter-paint-context.c 2023-03-19 10:55:05.000000000 +0000 +++ mutter-44.1/clutter/clutter/clutter-paint-context.c 2023-04-25 16:16:17.000000000 +0000 @@ -18,6 +18,7 @@ #include "clutter-build-config.h" #include "clutter-paint-context-private.h" +#include "clutter-frame.h" struct _ClutterPaintContext { @@ -28,6 +29,7 @@ GList *framebuffers; ClutterStageView *view; + ClutterFrame *frame; cairo_region_t *redraw_clip; GArray *clip_frusta; @@ -93,6 +95,7 @@ paint_context->framebuffers = NULL; g_clear_pointer (&paint_context->redraw_clip, cairo_region_destroy); g_clear_pointer (&paint_context->clip_frusta, g_array_unref); + g_clear_pointer (&paint_context->frame, clutter_frame_unref); } void @@ -196,3 +199,31 @@ { return paint_context->paint_flags; } + +void +clutter_paint_context_assign_frame (ClutterPaintContext *paint_context, + ClutterFrame *frame) +{ + g_assert (paint_context != NULL); + g_assert (paint_context->frame == NULL); + g_assert (frame != NULL); + + paint_context->frame = clutter_frame_ref (frame); +} + +/** + * clutter_paint_context_get_frame: (skip) + * @paint_context: The #ClutterPaintContext + * + * Retrieves the #ClutterFrame assigned to @paint_context, if any. A frame is + * only assigned when the paint context is created as part of a frame scheduled + * by the frame clock, and won't be assigned e.g. on offscreen paints. + * + * Returns: (transfer none)(nullable): The #ClutterFrame associated with the + * @paint_context, or %NULL + */ +ClutterFrame * +clutter_paint_context_get_frame (ClutterPaintContext *paint_context) +{ + return paint_context->frame; +} diff -Nru mutter-44.0/clutter/clutter/clutter-paint-context.h mutter-44.1/clutter/clutter/clutter-paint-context.h --- mutter-44.0/clutter/clutter/clutter-paint-context.h 2023-03-19 10:55:05.000000000 +0000 +++ mutter-44.1/clutter/clutter/clutter-paint-context.h 2023-04-25 16:16:17.000000000 +0000 @@ -75,4 +75,7 @@ CLUTTER_EXPORT ClutterPaintFlag clutter_paint_context_get_paint_flags (ClutterPaintContext *paint_context); +CLUTTER_EXPORT +ClutterFrame * clutter_paint_context_get_frame (ClutterPaintContext *paint_context); + #endif /* CLUTTER_PAINT_CONTEXT_H */ diff -Nru mutter-44.0/clutter/clutter/clutter-paint-context-private.h mutter-44.1/clutter/clutter/clutter-paint-context-private.h --- mutter-44.0/clutter/clutter/clutter-paint-context-private.h 2023-03-19 10:55:05.000000000 +0000 +++ mutter-44.1/clutter/clutter/clutter-paint-context-private.h 2023-04-25 16:16:17.000000000 +0000 @@ -33,4 +33,7 @@ const GArray * clutter_paint_context_get_clip_frusta (ClutterPaintContext *paint_context); +void clutter_paint_context_assign_frame (ClutterPaintContext *paint_context, + ClutterFrame *frame); + #endif /* CLUTTER_PAINT_CONTEXT_PRIVATE_H */ diff -Nru mutter-44.0/clutter/clutter/clutter-path.c mutter-44.1/clutter/clutter/clutter-path.c --- mutter-44.0/clutter/clutter/clutter-path.c 2023-03-19 10:55:05.000000000 +0000 +++ mutter-44.1/clutter/clutter/clutter-path.c 2023-04-25 16:16:17.000000000 +0000 @@ -211,19 +211,26 @@ clutter_value_transform_path_string (const GValue *src, GValue *dest) { - gchar *string = clutter_path_get_description (src->data[0].v_pointer); + if (src->data[0].v_pointer != NULL) + { + gchar *string = clutter_path_get_description (src->data[0].v_pointer); - g_value_take_string (dest, string); + g_value_take_string (dest, string); + } } static void clutter_value_transform_string_path (const GValue *src, GValue *dest) { - ClutterPath *new_path; + const char *str; - new_path = clutter_path_new_with_description (g_value_get_string (src)); - g_value_take_object (dest, new_path); + str = g_value_get_string (src); + if (str != NULL) + { + ClutterPath *new_path = clutter_path_new_with_description (str); + g_value_take_object (dest, new_path); + } } static void diff -Nru mutter-44.0/clutter/clutter/clutter-seat.c mutter-44.1/clutter/clutter/clutter-seat.c --- mutter-44.0/clutter/clutter/clutter-seat.c 2023-03-19 10:55:05.000000000 +0000 +++ mutter-44.1/clutter/clutter/clutter-seat.c 2023-04-25 16:16:17.000000000 +0000 @@ -679,6 +679,17 @@ return has_touchscreen; } +/** + * clutter_seat_query_state: + * @seat: a #ClutterSeat + * @device: a #ClutterInputDevice + * @sequence: (nullable): a #ClutterEventSequence + * @coords: (out caller-allocates) (optional): the coordinates of the pointer + * @modifiers: (out) (optional): the current #ClutterModifierType of the pointer + * + * Returns: %TRUE if @device (or the specific @sequence) is on the stage, %FALSE + * otherwise. + **/ gboolean clutter_seat_query_state (ClutterSeat *seat, ClutterInputDevice *device, diff -Nru mutter-44.0/clutter/clutter/clutter-stage.c mutter-44.1/clutter/clutter/clutter-stage.c --- mutter-44.0/clutter/clutter/clutter-stage.c 2023-03-19 10:55:05.000000000 +0000 +++ mutter-44.1/clutter/clutter/clutter-stage.c 2023-04-25 16:16:17.000000000 +0000 @@ -406,6 +406,7 @@ static void clutter_stage_do_paint_view (ClutterStage *stage, ClutterStageView *view, + ClutterFrame *frame, const cairo_region_t *redraw_clip) { ClutterPaintContext *paint_context; @@ -451,6 +452,9 @@ clip_frusta, CLUTTER_PAINT_FLAG_NONE); + if (frame) + clutter_paint_context_assign_frame (paint_context, frame); + clutter_actor_paint (CLUTTER_ACTOR (stage), paint_context); clutter_paint_context_destroy (paint_context); } @@ -1259,7 +1263,7 @@ const cairo_region_t *redraw_clip, ClutterFrame *frame) { - clutter_stage_do_paint_view (stage, view, redraw_clip); + clutter_stage_do_paint_view (stage, view, frame, redraw_clip); } static void @@ -1918,7 +1922,7 @@ } framebuffer = clutter_stage_view_get_framebuffer (view); - clutter_stage_do_paint_view (stage, view, clip); + clutter_stage_do_paint_view (stage, view, NULL, clip); cairo_region_destroy (clip); diff -Nru mutter-44.0/clutter/clutter/clutter-stage-view.c mutter-44.1/clutter/clutter/clutter-stage-view.c --- mutter-44.0/clutter/clutter/clutter-stage-view.c 2023-03-19 10:55:05.000000000 +0000 +++ mutter-44.1/clutter/clutter/clutter-stage-view.c 2023-04-25 16:16:17.000000000 +0000 @@ -50,6 +50,14 @@ static GParamSpec *obj_props[PROP_LAST]; +enum +{ + DESTROY, + N_SIGNALS +}; + +guint stage_view_signals[N_SIGNALS] = { 0 }; + typedef struct _ClutterStageViewPrivate { char *name; @@ -1467,6 +1475,8 @@ clutter_stage_view_get_instance_private (view); int i; + g_signal_emit (view, stage_view_signals[DESTROY], 0); + g_clear_pointer (&priv->name, g_free); g_clear_object (&priv->shadow.framebuffer); @@ -1607,6 +1617,14 @@ G_PARAM_STATIC_STRINGS); g_object_class_install_properties (object_class, PROP_LAST, obj_props); + + stage_view_signals[DESTROY] = + g_signal_new ("destroy", + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST, + 0, NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); } void diff -Nru mutter-44.0/clutter/meson.build mutter-44.1/clutter/meson.build --- mutter-44.0/clutter/meson.build 2023-03-19 10:55:05.000000000 +0000 +++ mutter-44.1/clutter/meson.build 2023-04-25 16:16:17.000000000 +0000 @@ -21,7 +21,6 @@ elif buildtype != 'plain' clutter_debug_c_args += [ '-DG_DISABLE_ASSERT', - '-DG_DISABLE_CHECKS', '-DG_DISABLE_CAST_CHECKS', ] endif diff -Nru mutter-44.0/cogl/meson.build mutter-44.1/cogl/meson.build --- mutter-44.0/cogl/meson.build 2023-03-19 10:55:05.000000000 +0000 +++ mutter-44.1/cogl/meson.build 2023-04-25 16:16:17.000000000 +0000 @@ -106,7 +106,6 @@ ] elif buildtype != 'plain' cogl_debug_c_args += [ - '-DG_DISABLE_CHECKS', '-DG_DISABLE_CAST_CHECKS' ] endif diff -Nru mutter-44.0/debian/changelog mutter-44.1/debian/changelog --- mutter-44.0/debian/changelog 2023-04-24 17:59:49.000000000 +0000 +++ mutter-44.1/debian/changelog 2023-05-19 20:18:13.000000000 +0000 @@ -1,3 +1,16 @@ +mutter (44.1-0ubuntu1) lunar; urgency=medium + + [ Jeremy Bícha ] + * New upstream release (LP: #2020225, LP: #2012717, LP: #2013216, + LP: #2015861, LP: #2017097) + * debian/libmutter-12-0.symbols: Add new symbols + * Drop 3 patches applied in new release + + [ Daniel van Vugt ] + * Update triple buffering patch for Mutter 44.1 (LP: #2017137) + + -- Jeremy Bícha Fri, 19 May 2023 16:18:13 -0400 + mutter (44.0-2ubuntu4.23.04.1) lunar; urgency=medium [ Marco Trevisan (Treviño) ] diff -Nru mutter-44.0/debian/control mutter-44.1/debian/control --- mutter-44.0/debian/control 2023-04-24 17:59:49.000000000 +0000 +++ mutter-44.1/debian/control 2023-05-19 20:18:13.000000000 +0000 @@ -89,8 +89,8 @@ Standards-Version: 4.6.2 XS-Debian-Vcs-Git: https://salsa.debian.org/gnome-team/mutter.git -b debian/unstable 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/lunar +Vcs-Browser: https://salsa.debian.org/gnome-team/mutter/tree/ubuntu/lunar Package: mutter Architecture: linux-any diff -Nru mutter-44.0/debian/control.in mutter-44.1/debian/control.in --- mutter-44.0/debian/control.in 2023-04-18 20:44:57.000000000 +0000 +++ mutter-44.1/debian/control.in 2023-05-19 20:18:13.000000000 +0000 @@ -85,8 +85,8 @@ Standards-Version: 4.6.2 XS-Debian-Vcs-Git: https://salsa.debian.org/gnome-team/mutter.git -b debian/unstable 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/lunar +Vcs-Browser: https://salsa.debian.org/gnome-team/mutter/tree/ubuntu/lunar Package: mutter Architecture: linux-any diff -Nru mutter-44.0/debian/gbp.conf mutter-44.1/debian/gbp.conf --- mutter-44.0/debian/gbp.conf 2023-04-18 20:44:57.000000000 +0000 +++ mutter-44.1/debian/gbp.conf 2023-05-19 20:18:13.000000000 +0000 @@ -1,6 +1,6 @@ [DEFAULT] pristine-tar = True -debian-branch = ubuntu/master +debian-branch = ubuntu/lunar debian-tag = ubuntu/%(version)s upstream-branch = upstream/latest diff -Nru mutter-44.0/debian/libmutter-12-0.symbols mutter-44.1/debian/libmutter-12-0.symbols --- mutter-44.0/debian/libmutter-12-0.symbols 2023-04-18 20:44:57.000000000 +0000 +++ mutter-44.1/debian/libmutter-12-0.symbols 2023-05-19 20:18:13.000000000 +0000 @@ -18,6 +18,7 @@ meta_backend_get_context@Base 43.0 meta_backend_get_core_idle_monitor@Base 43.0 meta_backend_get_current_logical_monitor@Base 43.0 + meta_backend_get_cursor_renderer@Base 44.1 meta_backend_get_cursor_tracker@Base 43.0 meta_backend_get_default_seat@Base 43.0 meta_backend_get_dnd@Base 43.0 @@ -144,6 +145,8 @@ meta_crtc_unassign_output@Base 43.0 meta_crtc_unset_config@Base 43.0 meta_cursor_get_type@Base 43.0 + meta_cursor_renderer_get_cursor@Base 44.1 + meta_cursor_sprite_wayland_get_type@Base 44.1 meta_cursor_tracker_get_for_display@Base 43.0 meta_cursor_tracker_get_hot@Base 43.0 meta_cursor_tracker_get_pointer@Base 43.0 @@ -227,6 +230,7 @@ meta_frame_flags_get_type@Base 43.0 meta_frame_native_ensure_kms_update@Base 44~rc meta_frame_native_from_frame@Base 44~rc + meta_frame_native_had_kms_update@Base 44.1 meta_frame_native_has_kms_update@Base 44~rc meta_frame_type_get_type@Base 43.0 meta_frame_type_to_string@Base 43.0 @@ -490,6 +494,7 @@ meta_output_is_underscanning@Base 43.0 meta_output_unassign_crtc@Base 43.0 meta_pad_action_type_get_type@Base 43.0 + meta_parse_monitor_mode@Base 44.1 meta_plugin_complete_display_change@Base 43.0 meta_plugin_destroy_completed@Base 43.0 meta_plugin_get_display@Base 43.0 @@ -788,6 +793,7 @@ meta_window_group_leader_changed@Base 43.0 meta_window_has_attached_dialogs@Base 43.0 meta_window_has_focus@Base 43.0 + meta_window_has_pointer@Base 44.1 meta_window_is_above@Base 43.0 meta_window_is_always_on_all_workspaces@Base 43.0 meta_window_is_ancestor_of_transient@Base 43.0 @@ -1474,6 +1480,7 @@ clutter_frame_clock_uninhibit@Base 43.0 clutter_frame_get_count@Base 44~beta clutter_frame_get_hints@Base 43.0 + clutter_frame_get_min_render_time_allowed@Base 44.1 clutter_frame_get_target_presentation_time@Base 44~beta clutter_frame_get_type@Base 44~beta clutter_frame_has_result@Base 43.0 @@ -1687,6 +1694,7 @@ clutter_page_turn_effect_set_period@Base 43.0 clutter_page_turn_effect_set_radius@Base 43.0 clutter_paint_context_destroy@Base 43.0 + clutter_paint_context_get_frame@Base 44.1 clutter_paint_context_get_framebuffer@Base 43.0 clutter_paint_context_get_paint_flags@Base 43.0 clutter_paint_context_get_redraw_clip@Base 43.0 diff -Nru mutter-44.0/debian/patches/backends-x11-Trap-errors-from-XIChangeProperty.patch mutter-44.1/debian/patches/backends-x11-Trap-errors-from-XIChangeProperty.patch --- mutter-44.0/debian/patches/backends-x11-Trap-errors-from-XIChangeProperty.patch 2023-04-18 20:44:57.000000000 +0000 +++ mutter-44.1/debian/patches/backends-x11-Trap-errors-from-XIChangeProperty.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,45 +0,0 @@ -From: Daniel van Vugt -Date: Fri, 14 Apr 2023 18:10:36 +0800 -Subject: backends/x11: Trap errors from XIChangeProperty - -And report them as warnings instead of crashing. - -https://launchpad.net/bugs/2014986 - -https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2960 ---- - src/backends/x11/meta-input-settings-x11.c | 12 ++++++++++++ - 1 file changed, 12 insertions(+) - -diff --git a/src/backends/x11/meta-input-settings-x11.c b/src/backends/x11/meta-input-settings-x11.c -index 4022351..9a0b37e 100644 ---- a/src/backends/x11/meta-input-settings-x11.c -+++ b/src/backends/x11/meta-input-settings-x11.c -@@ -170,6 +170,7 @@ change_property (MetaInputSettings *settings, - int device_id; - Atom property_atom; - guchar *data_ret; -+ int err; - - property_atom = XInternAtom (xdisplay, property, True); - if (!property_atom) -@@ -181,8 +182,19 @@ change_property (MetaInputSettings *settings, - if (!data_ret) - return; - -+ meta_clutter_x11_trap_x_errors (); - XIChangeProperty (xdisplay, device_id, property_atom, type, - format, XIPropModeReplace, data, nitems); -+ XSync (xdisplay, False); -+ err = meta_clutter_x11_untrap_x_errors (); -+ if (err) -+ { -+ g_warning ("XIChangeProperty failed on device %d property \"%s\" with X error %d", -+ device_id, -+ property, -+ err); -+ } -+ - meta_XFree (data_ret); - } - diff -Nru mutter-44.0/debian/patches/debian/Support-Dynamic-triple-double-buffering.patch mutter-44.1/debian/patches/debian/Support-Dynamic-triple-double-buffering.patch --- mutter-44.0/debian/patches/debian/Support-Dynamic-triple-double-buffering.patch 2023-04-18 20:44:57.000000000 +0000 +++ mutter-44.1/debian/patches/debian/Support-Dynamic-triple-double-buffering.patch 2023-05-19 20:18:13.000000000 +0000 @@ -12,17 +12,17 @@ If the previous frame is not running late then we stick to double buffering so there's no latency penalty when the system is able to maintain full frame rate. -Formatted for Debian (as of 43.3-51-ga6f23c151c) with: +Formatted for Debian (as of 44.1) with: git remote add vanvugt git@ssh.gitlab.gnome.org:vanvugt/mutter.git git fetch vanvugt -git merge --squash -e vanvugt/triple-buffering-v4 +git merge --squash -e vanvugt/triple-buffering-v4-44 And then git commit but using all this as the header instead of what git suggests. Also add Gbp-Pq: Topic debian Origin: https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1441 -Last-Update: 2023-03-22 +Last-Update: 2023-05-19 --- - clutter/clutter/clutter-frame-clock.c | 219 ++++++++++++--- + clutter/clutter/clutter-frame-clock.c | 230 ++++++++++++--- clutter/clutter/clutter-frame-clock.h | 11 +- clutter/clutter/clutter-frame-private.h | 1 + clutter/clutter/clutter-frame.c | 13 + @@ -41,19 +41,20 @@ src/backends/native/meta-kms-update.c | 3 +- src/backends/native/meta-kms.c | 9 + src/backends/native/meta-kms.h | 2 + - src/backends/native/meta-onscreen-native.c | 325 +++++++++++++++++----- + src/backends/native/meta-onscreen-native.c | 328 +++++++++++++++++----- src/backends/native/meta-onscreen-native.h | 2 + src/backends/native/meta-renderer-native.c | 34 ++- src/backends/native/meta-swap-chain.c | 149 ++++++++++ src/backends/native/meta-swap-chain.h | 48 ++++ src/meson.build | 2 + + src/tests/clutter/conform/event-delivery.c | 1 + src/tests/native-kms-render.c | 107 +++++-- - 26 files changed, 900 insertions(+), 276 deletions(-) + 27 files changed, 911 insertions(+), 280 deletions(-) create mode 100644 src/backends/native/meta-swap-chain.c create mode 100644 src/backends/native/meta-swap-chain.h diff --git a/clutter/clutter/clutter-frame-clock.c b/clutter/clutter/clutter-frame-clock.c -index eeba108..27affe1 100644 +index 3aeb290..b1d6f71 100644 --- a/clutter/clutter/clutter-frame-clock.c +++ b/clutter/clutter/clutter-frame-clock.c @@ -35,6 +35,15 @@ enum @@ -92,7 +93,7 @@ int64_t last_dispatch_lateness_us; int64_t last_presentation_time_us; int64_t next_update_time_us; -@@ -86,6 +97,9 @@ struct _ClutterFrameClock +@@ -87,6 +98,9 @@ struct _ClutterFrameClock int64_t vblank_duration_us; /* Last KMS buffer submission time. */ int64_t last_flip_time_us; @@ -102,7 +103,7 @@ /* Last time we promoted short term durations to long term ones */ int64_t longterm_promotion_us; -@@ -240,6 +254,12 @@ void +@@ -241,6 +255,12 @@ void clutter_frame_clock_notify_presented (ClutterFrameClock *frame_clock, ClutterFrameInfo *frame_info) { @@ -115,7 +116,7 @@ COGL_TRACE_BEGIN_SCOPED (ClutterFrameClockNotifyPresented, "Frame Clock (presented)"); -@@ -323,18 +343,38 @@ clutter_frame_clock_notify_presented (ClutterFrameClock *frame_clock, +@@ -324,18 +344,38 @@ clutter_frame_clock_notify_presented (ClutterFrameClock *frame_clock, frame_info->gpu_rendering_duration_ns != 0) { int64_t dispatch_to_swap_us, swap_to_rendering_done_us, swap_to_flip_us; @@ -157,7 +158,7 @@ frame_clock->last_dispatch_lateness_us, dispatch_to_swap_us, swap_to_rendering_done_us, -@@ -351,7 +391,8 @@ clutter_frame_clock_notify_presented (ClutterFrameClock *frame_clock, +@@ -352,7 +392,8 @@ clutter_frame_clock_notify_presented (ClutterFrameClock *frame_clock, } else { @@ -167,7 +168,7 @@ frame_clock->last_dispatch_lateness_us); } -@@ -382,11 +423,18 @@ clutter_frame_clock_notify_presented (ClutterFrameClock *frame_clock, +@@ -383,11 +424,18 @@ clutter_frame_clock_notify_presented (ClutterFrameClock *frame_clock, case CLUTTER_FRAME_CLOCK_STATE_SCHEDULED: g_warn_if_reached (); break; @@ -188,7 +189,7 @@ } } -@@ -402,11 +450,18 @@ clutter_frame_clock_notify_ready (ClutterFrameClock *frame_clock) +@@ -403,11 +451,18 @@ clutter_frame_clock_notify_ready (ClutterFrameClock *frame_clock) case CLUTTER_FRAME_CLOCK_STATE_SCHEDULED: g_warn_if_reached (); break; @@ -209,7 +210,24 @@ } } -@@ -458,8 +513,6 @@ clutter_frame_clock_compute_max_render_time_us (ClutterFrameClock *frame_clock) +@@ -426,7 +481,15 @@ clutter_frame_clock_compute_max_render_time_us (ClutterFrameClock *frame_clock) + if (!frame_clock->got_measurements_last_frame || + G_UNLIKELY (clutter_paint_debug_flags & + CLUTTER_DEBUG_DISABLE_DYNAMIC_MAX_RENDER_TIME)) +- return refresh_interval_us * SYNC_DELAY_FALLBACK_FRACTION; ++ { ++ int64_t ret = refresh_interval_us * SYNC_DELAY_FALLBACK_FRACTION; ++ ++ if (frame_clock->state == CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE && ++ triple_buffering_mode != TRIPLE_BUFFERING_MODE_NEVER) ++ ret += refresh_interval_us; ++ ++ return ret; ++ } + + max_dispatch_lateness_us = + MAX (frame_clock->longterm.max_dispatch_lateness_us, +@@ -459,8 +522,6 @@ clutter_frame_clock_compute_max_render_time_us (ClutterFrameClock *frame_clock) frame_clock->vblank_duration_us + clutter_max_render_time_constant_us; @@ -218,7 +236,7 @@ return max_render_time_us; } -@@ -473,7 +526,7 @@ calculate_next_update_time_us (ClutterFrameClock *frame_clock, +@@ -475,7 +536,7 @@ calculate_next_update_time_us (ClutterFrameClock *frame_clock, int64_t refresh_interval_us; int64_t min_render_time_allowed_us; int64_t max_render_time_allowed_us; @@ -227,7 +245,7 @@ int64_t next_update_time_us; now_us = g_get_monotonic_time (); -@@ -517,7 +570,24 @@ calculate_next_update_time_us (ClutterFrameClock *frame_clock, +@@ -520,7 +581,24 @@ calculate_next_update_time_us (ClutterFrameClock *frame_clock, * */ last_presentation_time_us = frame_clock->last_presentation_time_us; @@ -253,7 +271,7 @@ /* * However, the last presentation could have happened more than a frame ago. -@@ -631,8 +701,12 @@ clutter_frame_clock_inhibit (ClutterFrameClock *frame_clock) +@@ -635,8 +713,12 @@ clutter_frame_clock_inhibit (ClutterFrameClock *frame_clock) frame_clock->pending_reschedule = TRUE; frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_IDLE; break; @@ -268,7 +286,7 @@ break; } -@@ -669,9 +743,15 @@ clutter_frame_clock_schedule_update_now (ClutterFrameClock *frame_clock) +@@ -673,9 +755,15 @@ clutter_frame_clock_schedule_update_now (ClutterFrameClock *frame_clock) case CLUTTER_FRAME_CLOCK_STATE_IDLE: case CLUTTER_FRAME_CLOCK_STATE_SCHEDULED: next_update_time_us = g_get_monotonic_time (); @@ -286,7 +304,7 @@ frame_clock->pending_reschedule = TRUE; frame_clock->pending_reschedule_now = TRUE; return; -@@ -681,7 +761,6 @@ clutter_frame_clock_schedule_update_now (ClutterFrameClock *frame_clock) +@@ -685,7 +773,6 @@ clutter_frame_clock_schedule_update_now (ClutterFrameClock *frame_clock) frame_clock->next_update_time_us = next_update_time_us; g_source_set_ready_time (frame_clock->source, next_update_time_us); @@ -294,7 +312,7 @@ frame_clock->is_next_presentation_time_valid = FALSE; } -@@ -689,6 +768,10 @@ void +@@ -693,6 +780,10 @@ void clutter_frame_clock_schedule_update (ClutterFrameClock *frame_clock) { int64_t next_update_time_us = -1; @@ -305,7 +323,7 @@ if (frame_clock->inhibit_count > 0) { -@@ -700,6 +783,7 @@ clutter_frame_clock_schedule_update (ClutterFrameClock *frame_clock) +@@ -704,6 +795,7 @@ clutter_frame_clock_schedule_update (ClutterFrameClock *frame_clock) { case CLUTTER_FRAME_CLOCK_STATE_INIT: next_update_time_us = g_get_monotonic_time (); @@ -313,8 +331,8 @@ break; case CLUTTER_FRAME_CLOCK_STATE_IDLE: calculate_next_update_time_us (frame_clock, -@@ -707,11 +791,36 @@ clutter_frame_clock_schedule_update (ClutterFrameClock *frame_clock) - &frame_clock->next_presentation_time_us); +@@ -712,11 +804,37 @@ clutter_frame_clock_schedule_update (ClutterFrameClock *frame_clock) + &frame_clock->min_render_time_allowed_us); frame_clock->is_next_presentation_time_valid = (frame_clock->next_presentation_time_us != 0); + frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_SCHEDULED; @@ -333,7 +351,8 @@ + case TRIPLE_BUFFERING_MODE_AUTO: + calculate_next_update_time_us (frame_clock, + &next_update_time_us, -+ &frame_clock->next_presentation_time_us); ++ &frame_clock->next_presentation_time_us, ++ &frame_clock->min_render_time_allowed_us); + frame_clock->is_next_presentation_time_valid = + (frame_clock->next_presentation_time_us != 0); + frame_clock->state = @@ -352,7 +371,7 @@ frame_clock->pending_reschedule = TRUE; return; } -@@ -720,7 +829,6 @@ clutter_frame_clock_schedule_update (ClutterFrameClock *frame_clock) +@@ -725,7 +843,6 @@ clutter_frame_clock_schedule_update (ClutterFrameClock *frame_clock) frame_clock->next_update_time_us = next_update_time_us; g_source_set_ready_time (frame_clock->source, next_update_time_us); @@ -360,7 +379,7 @@ } static void -@@ -751,7 +859,7 @@ clutter_frame_clock_dispatch (ClutterFrameClock *frame_clock, +@@ -756,7 +873,7 @@ clutter_frame_clock_dispatch (ClutterFrameClock *frame_clock, frame_clock->refresh_interval_us; lateness_us = time_us - ideal_dispatch_time_us; @@ -369,7 +388,7 @@ frame_clock->last_dispatch_lateness_us = 0; else frame_clock->last_dispatch_lateness_us = lateness_us; -@@ -760,10 +868,25 @@ clutter_frame_clock_dispatch (ClutterFrameClock *frame_clock, +@@ -765,10 +882,25 @@ clutter_frame_clock_dispatch (ClutterFrameClock *frame_clock, MAX (frame_clock->shortterm.max_dispatch_lateness_us, frame_clock->last_dispatch_lateness_us); @@ -396,7 +415,7 @@ frame_count = frame_clock->frame_count++; -@@ -791,25 +914,31 @@ clutter_frame_clock_dispatch (ClutterFrameClock *frame_clock, +@@ -797,25 +929,31 @@ clutter_frame_clock_dispatch (ClutterFrameClock *frame_clock, result = iface->frame (frame_clock, frame, frame_clock->listener.user_data); COGL_TRACE_END (ClutterFrameClockFrame); @@ -406,11 +425,11 @@ - case CLUTTER_FRAME_CLOCK_STATE_INIT: - case CLUTTER_FRAME_CLOCK_STATE_PENDING_PRESENTED: - g_warn_if_reached (); -+ case CLUTTER_FRAME_RESULT_PENDING_PRESENTED: - break; +- break; - case CLUTTER_FRAME_CLOCK_STATE_IDLE: - case CLUTTER_FRAME_CLOCK_STATE_SCHEDULED: -- break; ++ case CLUTTER_FRAME_RESULT_PENDING_PRESENTED: + break; - case CLUTTER_FRAME_CLOCK_STATE_DISPATCHING: - switch (result) + case CLUTTER_FRAME_RESULT_IDLE: @@ -440,7 +459,7 @@ } break; } -@@ -842,10 +971,13 @@ frame_clock_source_dispatch (GSource *source, +@@ -848,10 +986,13 @@ frame_clock_source_dispatch (GSource *source, } void @@ -456,7 +475,7 @@ } GString * -@@ -957,8 +1089,6 @@ clutter_frame_clock_dispose (GObject *object) +@@ -963,8 +1104,6 @@ clutter_frame_clock_dispose (GObject *object) { ClutterFrameClock *frame_clock = CLUTTER_FRAME_CLOCK (object); @@ -465,7 +484,7 @@ if (frame_clock->source) { g_signal_emit (frame_clock, signals[DESTROY], 0); -@@ -979,6 +1109,15 @@ static void +@@ -985,6 +1124,15 @@ static void clutter_frame_clock_class_init (ClutterFrameClockClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); @@ -511,10 +530,10 @@ GString * clutter_frame_clock_get_max_render_time_debug_info (ClutterFrameClock *frame_clock); diff --git a/clutter/clutter/clutter-frame-private.h b/clutter/clutter/clutter-frame-private.h -index 41dc9b3..bffc0e7 100644 +index 1eceb8b..fb97abe 100644 --- a/clutter/clutter/clutter-frame-private.h +++ b/clutter/clutter/clutter-frame-private.h -@@ -34,6 +34,7 @@ struct _ClutterFrame +@@ -35,6 +35,7 @@ struct _ClutterFrame gboolean has_result; ClutterFrameResult result; @@ -523,10 +542,10 @@ CLUTTER_EXPORT diff --git a/clutter/clutter/clutter-frame.c b/clutter/clutter/clutter-frame.c -index 98088d7..871de80 100644 +index 85baef2..413ce9c 100644 --- a/clutter/clutter/clutter-frame.c +++ b/clutter/clutter/clutter-frame.c -@@ -98,3 +98,16 @@ clutter_frame_set_result (ClutterFrame *frame, +@@ -113,3 +113,16 @@ clutter_frame_set_result (ClutterFrame *frame, frame->result = result; frame->has_result = TRUE; } @@ -544,10 +563,10 @@ + return frame->hints; +} diff --git a/clutter/clutter/clutter-frame.h b/clutter/clutter/clutter-frame.h -index 1837816..8df7fdf 100644 +index 6bac3f4..fa97e8b 100644 --- a/clutter/clutter/clutter-frame.h +++ b/clutter/clutter/clutter-frame.h -@@ -51,6 +51,13 @@ void clutter_frame_set_result (ClutterFrame *frame, +@@ -55,6 +55,13 @@ void clutter_frame_set_result (ClutterFrame *frame, CLUTTER_EXPORT gboolean clutter_frame_has_result (ClutterFrame *frame); @@ -562,10 +581,10 @@ #endif /* CLUTTER_FRAME_H */ diff --git a/clutter/clutter/clutter-stage-view.c b/clutter/clutter/clutter-stage-view.c -index f489988..d031e60 100644 +index 5f66d60..9e82115 100644 --- a/clutter/clutter/clutter-stage-view.c +++ b/clutter/clutter/clutter-stage-view.c -@@ -1258,8 +1258,9 @@ handle_frame_clock_frame (ClutterFrameClock *frame_clock, +@@ -1266,8 +1266,9 @@ handle_frame_clock_frame (ClutterFrameClock *frame_clock, _clutter_stage_window_redraw_view (stage_window, view, frame); @@ -609,10 +628,10 @@ cogl_onscreen_add_frame_callback (CoglOnscreen *onscreen, CoglFrameCallback callback, diff --git a/src/backends/meta-stage-impl.c b/src/backends/meta-stage-impl.c -index 31e07d9..18f26d7 100644 +index db94c7e..aed2296 100644 --- a/src/backends/meta-stage-impl.c +++ b/src/backends/meta-stage-impl.c -@@ -740,6 +740,8 @@ meta_stage_impl_redraw_view (ClutterStageWindow *stage_window, +@@ -770,6 +770,8 @@ meta_stage_impl_redraw_view (ClutterStageWindow *stage_window, { g_autoptr (GError) error = NULL; @@ -622,7 +641,7 @@ stage_view, scanout, diff --git a/src/backends/native/meta-cursor-renderer-native.c b/src/backends/native/meta-cursor-renderer-native.c -index f1b7459..8080098 100644 +index e524766..b05e228 100644 --- a/src/backends/native/meta-cursor-renderer-native.c +++ b/src/backends/native/meta-cursor-renderer-native.c @@ -59,19 +59,6 @@ @@ -797,7 +816,7 @@ } static void -@@ -1423,35 +1343,7 @@ load_cursor_sprite_gbm_buffer_for_gpu (MetaCursorRendererNative *native, +@@ -1427,35 +1347,7 @@ load_cursor_sprite_gbm_buffer_for_gpu (MetaCursorRendererNative *native, return; } @@ -834,7 +853,7 @@ } static gboolean -@@ -1638,7 +1530,7 @@ realize_cursor_sprite_from_wl_buffer_for_gpu (MetaCursorRenderer *renderer, +@@ -1642,7 +1534,7 @@ realize_cursor_sprite_from_wl_buffer_for_gpu (MetaCursorRenderer *renderer, if (!cursor_renderer_gpu_data || cursor_renderer_gpu_data->hw_cursor_broken) return; @@ -843,7 +862,7 @@ is_cursor_scale_and_transform_valid (renderer, cursor_sprite)) return; -@@ -1783,8 +1675,8 @@ realize_cursor_sprite_from_wl_buffer_for_gpu (MetaCursorRenderer *renderer, +@@ -1787,8 +1679,8 @@ realize_cursor_sprite_from_wl_buffer_for_gpu (MetaCursorRenderer *renderer, return; } @@ -854,7 +873,7 @@ } } #endif -@@ -1808,7 +1700,7 @@ realize_cursor_sprite_from_xcursor_for_gpu (MetaCursorRenderer *renderer, +@@ -1812,7 +1704,7 @@ realize_cursor_sprite_from_xcursor_for_gpu (MetaCursorRenderer *renderer, if (!cursor_renderer_gpu_data || cursor_renderer_gpu_data->hw_cursor_broken) return; @@ -864,7 +883,7 @@ return; diff --git a/src/backends/native/meta-kms-crtc.c b/src/backends/native/meta-kms-crtc.c -index 556f853..1ec84e8 100644 +index e540542..48e864c 100644 --- a/src/backends/native/meta-kms-crtc.c +++ b/src/backends/native/meta-kms-crtc.c @@ -46,6 +46,8 @@ struct _MetaKmsCrtc @@ -889,7 +908,7 @@ gboolean meta_kms_crtc_is_active (MetaKmsCrtc *crtc) { -@@ -468,12 +476,23 @@ meta_kms_crtc_new (MetaKmsImplDevice *impl_device, +@@ -463,12 +471,23 @@ meta_kms_crtc_new (MetaKmsImplDevice *impl_device, return crtc; } @@ -913,7 +932,7 @@ G_OBJECT_CLASS (meta_kms_crtc_parent_class)->finalize (object); } -@@ -483,6 +502,7 @@ meta_kms_crtc_init (MetaKmsCrtc *crtc) +@@ -478,6 +497,7 @@ meta_kms_crtc_init (MetaKmsCrtc *crtc) { crtc->current_state.gamma.size = 0; crtc->current_state.gamma.value = NULL; @@ -921,7 +940,7 @@ } static void -@@ -490,5 +510,6 @@ meta_kms_crtc_class_init (MetaKmsCrtcClass *klass) +@@ -485,5 +505,6 @@ meta_kms_crtc_class_init (MetaKmsCrtcClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); @@ -982,7 +1001,7 @@ &error)) goto err; diff --git a/src/backends/native/meta-kms-impl-device-simple.c b/src/backends/native/meta-kms-impl-device-simple.c -index 8cf683a..4257cbb 100644 +index 341d54c..c739788 100644 --- a/src/backends/native/meta-kms-impl-device-simple.c +++ b/src/backends/native/meta-kms-impl-device-simple.c @@ -486,6 +486,8 @@ process_mode_set (MetaKmsImplDevice *impl_device, @@ -1119,7 +1138,7 @@ static gboolean diff --git a/src/backends/native/meta-kms-impl-device.c b/src/backends/native/meta-kms-impl-device.c -index ef2890f..c50ec12 100644 +index d56636d..b7a0ddd 100644 --- a/src/backends/native/meta-kms-impl-device.c +++ b/src/backends/native/meta-kms-impl-device.c @@ -1259,11 +1259,25 @@ meta_kms_impl_device_init_mode_setting (MetaKmsImplDevice *impl_device, @@ -1238,7 +1257,7 @@ MetaKmsFlags flags, GError **error); diff --git a/src/backends/native/meta-onscreen-native.c b/src/backends/native/meta-onscreen-native.c -index 3fc0200..4e056ab 100644 +index 1ab117e..1c157ec 100644 --- a/src/backends/native/meta-onscreen-native.c +++ b/src/backends/native/meta-onscreen-native.c @@ -72,7 +72,7 @@ typedef struct _MetaOnscreenNativeSecondaryGpuState @@ -1346,15 +1365,24 @@ } static int64_t -@@ -293,6 +283,7 @@ page_flip_feedback_ready (MetaKmsCrtc *kms_crtc, - g_warn_if_fail (!onscreen_native->gbm.next_fb); +@@ -284,15 +274,13 @@ page_flip_feedback_ready (MetaKmsCrtc *kms_crtc, + CoglFramebuffer *framebuffer = + clutter_stage_view_get_onscreen (CLUTTER_STAGE_VIEW (view)); + CoglOnscreen *onscreen = COGL_ONSCREEN (framebuffer); +- MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen); + CoglFrameInfo *frame_info; + + frame_info = cogl_onscreen_peek_head_frame_info (onscreen); + frame_info->flags |= COGL_FRAME_INFO_FLAG_SYMBOLIC; +- g_warn_if_fail (!onscreen_native->gbm.next_fb); +- meta_onscreen_native_notify_frame_complete (onscreen); + try_post_latest_swap (onscreen); } static void -@@ -342,7 +333,7 @@ page_flip_feedback_discarded (MetaKmsCrtc *kms_crtc, +@@ -342,7 +330,7 @@ page_flip_feedback_discarded (MetaKmsCrtc *kms_crtc, frame_info->flags |= COGL_FRAME_INFO_FLAG_SYMBOLIC; meta_onscreen_native_notify_frame_complete (onscreen); @@ -1363,7 +1391,7 @@ } static const MetaKmsPageFlipListenerVtable page_flip_listener_vtable = { -@@ -403,18 +394,40 @@ custom_egl_stream_page_flip (gpointer custom_page_flip_data, +@@ -403,18 +391,40 @@ custom_egl_stream_page_flip (gpointer custom_page_flip_data, } #endif /* HAVE_EGL_DEVICE */ @@ -1374,8 +1402,7 @@ { CoglFrameInfo *frame_info; + MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen); - -- meta_onscreen_native_swap_drm_fb (onscreen); ++ + /* Remember we can't compare stalled_fb because it's not used by + * META_RENDERER_NATIVE_MODE_EGL_DEVICE. So we judge stalled to be whenever + * swaps_pending > 1. @@ -1384,7 +1411,8 @@ + return; + + onscreen_native->swaps_pending--; -+ + +- meta_onscreen_native_swap_drm_fb (onscreen); + g_clear_object (&onscreen_native->gbm.stalled_fb); frame_info = cogl_onscreen_peek_tail_frame_info (onscreen); @@ -1407,7 +1435,7 @@ static void meta_onscreen_native_flip_crtc (CoglOnscreen *onscreen, MetaRendererView *view, -@@ -431,7 +444,7 @@ meta_onscreen_native_flip_crtc (CoglOnscreen *onscreen, +@@ -431,7 +441,7 @@ meta_onscreen_native_flip_crtc (CoglOnscreen *onscreen, MetaKmsCrtc *kms_crtc = meta_crtc_kms_get_kms_crtc (crtc_kms); MetaRendererNativeGpuData *renderer_gpu_data; MetaGpuKms *gpu_kms; @@ -1416,7 +1444,7 @@ MetaKmsPlaneAssignment *plane_assignment; COGL_TRACE_BEGIN_SCOPED (MetaOnscreenNativeFlipCrtcs, -@@ -446,7 +459,7 @@ meta_onscreen_native_flip_crtc (CoglOnscreen *onscreen, +@@ -446,7 +456,7 @@ meta_onscreen_native_flip_crtc (CoglOnscreen *onscreen, switch (renderer_gpu_data->mode) { case META_RENDERER_NATIVE_MODE_GBM: @@ -1425,7 +1453,7 @@ plane_assignment = meta_crtc_kms_assign_primary_plane (crtc_kms, buffer, -@@ -457,6 +470,11 @@ meta_onscreen_native_flip_crtc (CoglOnscreen *onscreen, +@@ -457,6 +467,11 @@ meta_onscreen_native_flip_crtc (CoglOnscreen *onscreen, meta_kms_plane_assignment_set_fb_damage (plane_assignment, rectangles, n_rectangles); } @@ -1437,7 +1465,7 @@ break; case META_RENDERER_NATIVE_MODE_SURFACELESS: g_assert_not_reached (); -@@ -698,12 +716,17 @@ static MetaDrmBufferDumb * +@@ -698,12 +713,17 @@ static MetaDrmBufferDumb * secondary_gpu_get_next_dumb_buffer (MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state) { MetaDrmBufferDumb *current_dumb_fb; @@ -1459,7 +1487,7 @@ } static MetaDrmBuffer * -@@ -1041,7 +1064,6 @@ on_swap_buffer_update_result (const MetaKmsFeedback *kms_feedback, +@@ -1041,7 +1061,6 @@ on_swap_buffer_update_result (const MetaKmsFeedback *kms_feedback, frame_info->flags |= COGL_FRAME_INFO_FLAG_SYMBOLIC; meta_onscreen_native_notify_frame_complete (onscreen); @@ -1467,7 +1495,7 @@ } static void -@@ -1058,31 +1080,35 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, +@@ -1058,31 +1077,35 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, CoglRendererEGL *cogl_renderer_egl = cogl_renderer->winsys; MetaRendererNativeGpuData *renderer_gpu_data = cogl_renderer_egl->platform; MetaRendererNative *renderer_native = renderer_gpu_data->renderer_native; @@ -1513,7 +1541,7 @@ secondary_gpu_fb = update_secondary_gpu_state_pre_swap_buffers (onscreen, rectangles, -@@ -1138,7 +1164,15 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, +@@ -1138,7 +1161,15 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, switch (renderer_gpu_data->mode) { case META_RENDERER_NATIVE_MODE_GBM: @@ -1530,7 +1558,7 @@ if (onscreen_native->secondary_gpu_state) g_set_object (&onscreen_native->gbm.next_fb, secondary_gpu_fb); else -@@ -1152,6 +1186,9 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, +@@ -1152,6 +1183,9 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, #endif } @@ -1540,7 +1568,7 @@ /* * If we changed EGL context, cogl will have the wrong idea about what is * current, making it fail to set it when it needs to. Avoid that by making -@@ -1161,12 +1198,82 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, +@@ -1161,12 +1195,82 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, if (egl_context_changed) _cogl_winsys_egl_ensure_current (cogl_display); @@ -1625,7 +1653,7 @@ kms_update = meta_frame_native_ensure_kms_update (frame_native, kms_device); meta_kms_update_add_result_listener (kms_update, -@@ -1179,15 +1286,14 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, +@@ -1179,15 +1283,14 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, onscreen_native->crtc, kms_update, META_KMS_PAGE_FLIP_LISTENER_FLAG_NONE, @@ -1644,7 +1672,7 @@ return; } -@@ -1207,8 +1313,6 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, +@@ -1207,8 +1310,6 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, kms_update = meta_frame_native_steal_kms_update (frame_native); meta_renderer_native_queue_mode_set_update (renderer_native, kms_update); @@ -1653,7 +1681,7 @@ return; } else if (meta_renderer_native_has_pending_mode_set (renderer_native)) -@@ -1222,8 +1326,6 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, +@@ -1222,8 +1323,6 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, meta_frame_native_steal_kms_update (frame_native); meta_renderer_native_post_mode_set_updates (renderer_native); @@ -1662,7 +1690,7 @@ return; } break; -@@ -1239,8 +1341,6 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, +@@ -1239,8 +1338,6 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, kms_update); meta_renderer_native_post_mode_set_updates (renderer_native); @@ -1671,7 +1699,7 @@ return; } break; -@@ -1256,7 +1356,6 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, +@@ -1256,7 +1353,6 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, kms_feedback = meta_kms_device_process_update_sync (kms_device, kms_update, META_KMS_UPDATE_FLAG_NONE); @@ -1679,7 +1707,7 @@ } gboolean -@@ -1301,6 +1400,7 @@ on_scanout_update_result (const MetaKmsFeedback *kms_feedback, +@@ -1301,6 +1397,7 @@ on_scanout_update_result (const MetaKmsFeedback *kms_feedback, CoglOnscreen *onscreen = COGL_ONSCREEN (onscreen_native); const GError *error; CoglFrameInfo *frame_info; @@ -1687,7 +1715,7 @@ error = meta_kms_feedback_get_error (kms_feedback); if (!error) -@@ -1314,8 +1414,7 @@ on_scanout_update_result (const MetaKmsFeedback *kms_feedback, +@@ -1314,8 +1411,7 @@ on_scanout_update_result (const MetaKmsFeedback *kms_feedback, g_warning ("Direct scanout page flip failed: %s", error->message); @@ -1697,7 +1725,7 @@ clutter_stage_view_add_redraw_clip (view, NULL); clutter_stage_view_schedule_update_now (view); } -@@ -1324,7 +1423,6 @@ on_scanout_update_result (const MetaKmsFeedback *kms_feedback, +@@ -1324,7 +1420,6 @@ on_scanout_update_result (const MetaKmsFeedback *kms_feedback, frame_info->flags |= COGL_FRAME_INFO_FLAG_SYMBOLIC; meta_onscreen_native_notify_frame_complete (onscreen); @@ -1705,7 +1733,7 @@ } static gboolean -@@ -1375,6 +1473,18 @@ meta_onscreen_native_direct_scanout (CoglOnscreen *onscreen, +@@ -1375,6 +1470,18 @@ meta_onscreen_native_direct_scanout (CoglOnscreen *onscreen, return FALSE; } @@ -1724,7 +1752,7 @@ renderer_gpu_data = meta_renderer_native_get_gpu_data (renderer_native, render_gpu); -@@ -1414,6 +1524,8 @@ meta_onscreen_native_direct_scanout (CoglOnscreen *onscreen, +@@ -1414,6 +1521,8 @@ meta_onscreen_native_direct_scanout (CoglOnscreen *onscreen, kms_device = meta_kms_crtc_get_device (kms_crtc); kms_update = meta_frame_native_ensure_kms_update (frame_native, kms_device); @@ -1733,7 +1761,7 @@ meta_kms_update_add_result_listener (kms_update, on_scanout_update_result, onscreen_native); -@@ -1535,7 +1647,20 @@ meta_onscreen_native_finish_frame (CoglOnscreen *onscreen, +@@ -1558,7 +1667,20 @@ meta_onscreen_native_finish_frame (CoglOnscreen *onscreen, MetaKmsDevice *kms_device = meta_kms_crtc_get_device (kms_crtc); MetaFrameNative *frame_native = meta_frame_native_from_frame (frame); MetaKmsUpdate *kms_update; @@ -1755,7 +1783,7 @@ kms_update = meta_frame_native_steal_kms_update (frame_native); if (!kms_update) -@@ -1544,6 +1669,42 @@ meta_onscreen_native_finish_frame (CoglOnscreen *onscreen, +@@ -1567,6 +1689,42 @@ meta_onscreen_native_finish_frame (CoglOnscreen *onscreen, return; } @@ -1795,10 +1823,10 @@ + MetaKmsDevice *kms_device = meta_kms_crtc_get_device (kms_crtc); + g_autoptr (MetaKmsFeedback) kms_feedback = NULL; + - meta_kms_update_add_page_flip_listener (kms_update, - kms_crtc, - &page_flip_listener_vtable, -@@ -1560,7 +1721,17 @@ meta_onscreen_native_finish_frame (CoglOnscreen *onscreen, + meta_kms_update_add_result_listener (kms_update, + on_finish_frame_update_result, + onscreen_native); +@@ -1587,7 +1745,17 @@ meta_onscreen_native_finish_frame (CoglOnscreen *onscreen, kms_feedback = meta_kms_device_process_update_sync (kms_device, kms_update, META_KMS_UPDATE_FLAG_NONE); @@ -1817,7 +1845,7 @@ } static gboolean -@@ -2387,7 +2558,7 @@ meta_onscreen_native_dispose (GObject *object) +@@ -2414,7 +2582,7 @@ meta_onscreen_native_dispose (GObject *object) { case META_RENDERER_NATIVE_MODE_GBM: g_clear_object (&onscreen_native->gbm.next_fb); @@ -1826,7 +1854,7 @@ break; case META_RENDERER_NATIVE_MODE_SURFACELESS: g_assert_not_reached (); -@@ -2421,6 +2592,10 @@ meta_onscreen_native_dispose (GObject *object) +@@ -2448,6 +2616,10 @@ meta_onscreen_native_dispose (GObject *object) g_clear_object (&onscreen_native->output); g_clear_object (&onscreen_native->crtc); @@ -2142,6 +2170,18 @@ 'backends/native/meta-udev.c', 'backends/native/meta-udev.h', 'backends/native/meta-virtual-input-device-native.c', +diff --git a/src/tests/clutter/conform/event-delivery.c b/src/tests/clutter/conform/event-delivery.c +index 0f3ca25..0c9fdf7 100644 +--- a/src/tests/clutter/conform/event-delivery.c ++++ b/src/tests/clutter/conform/event-delivery.c +@@ -326,6 +326,7 @@ event_delivery_implicit_grab_cancelled (void) + n_child_1_leave_events = n_child_2_leave_events = n_stage_leave_events = 0; + n_action_sequences_cancelled = 0; + clutter_actor_destroy (child_1); ++ wait_stage_updated (&was_updated); + g_assert_cmpint (n_child_1_enter_events, ==, 0); + g_assert_cmpint (n_child_1_leave_events, ==, 0); + g_assert_cmpint (n_action_sequences_cancelled, ==, 1); diff --git a/src/tests/native-kms-render.c b/src/tests/native-kms-render.c index 1557b76..c482d07 100644 --- a/src/tests/native-kms-render.c diff -Nru mutter-44.0/debian/patches/frames-window-tracker-Select-StructureNotifyMask-X11-even.patch mutter-44.1/debian/patches/frames-window-tracker-Select-StructureNotifyMask-X11-even.patch --- mutter-44.0/debian/patches/frames-window-tracker-Select-StructureNotifyMask-X11-even.patch 2023-04-18 20:44:57.000000000 +0000 +++ mutter-44.1/debian/patches/frames-window-tracker-Select-StructureNotifyMask-X11-even.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,41 +0,0 @@ -From: =?utf-8?b?Ik1hcmNvIFRyZXZpc2FuIChUcmV2acOxbyki?= -Date: Mon, 3 Apr 2023 20:59:16 +0200 -Subject: frames/window-tracker: Select StructureNotifyMask X11 events - -The window tracker is filtering XEvents manually as it only requires a -subset of the ones that Gdk listens to in the root window, and this is -nice, but we were restricting the set a bit too much because due to this -we were not notified when an xsettings manager was available, and thus -in case gsd-xsettings was launched after meta-window-tracker (a normal -scenario under X11), no xsetting was actually applied to the decoration -windows. - -As per this, the default settings were used for everything and never -updated, until a restart of the window-tracker. - -In order to be able to monitor the XSettings changes at startup, we also -need to select the StructureNotifyMask as gtk always do by default. - -See also: - https://gitlab.gnome.org/GNOME/gtk/-/blob/4.11.1/gdk/x11/gdkscreen-x11.c#L947-950 - -Fixes: #2580 -Part-of: - -Origin: https://gitlab.gnome.org/GNOME/mutter/-/commit/20e2adc ---- - src/frames/meta-window-tracker.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/src/frames/meta-window-tracker.c b/src/frames/meta-window-tracker.c -index 39de518..e241e56 100644 ---- a/src/frames/meta-window-tracker.c -+++ b/src/frames/meta-window-tracker.c -@@ -341,6 +341,7 @@ meta_window_tracker_constructed (GObject *object) - XSelectInput (xdisplay, xroot, - KeyPressMask | - PropertyChangeMask | -+ StructureNotifyMask | - SubstructureNotifyMask); - - g_signal_connect (display, "xevent", diff -Nru mutter-44.0/debian/patches/series mutter-44.1/debian/patches/series --- mutter-44.0/debian/patches/series 2023-04-18 20:55:05.000000000 +0000 +++ mutter-44.1/debian/patches/series 2023-05-19 20:18:13.000000000 +0000 @@ -1,5 +1,3 @@ -frames-window-tracker-Select-StructureNotifyMask-X11-even.patch -tests-Use-a-more-interoperable-path-to-bash.patch meson-add-back-default_driver-option.patch tests-Mark-view-verification-tests-as-incomplete-in-big-e.patch debian/meson-Do-not-mark-CI-test-tools-as-required.patch @@ -9,10 +7,9 @@ debian/wayland-data-device-Allow-any-drag-timestamp-as-drag-star.patch debian/Support-Dynamic-triple-double-buffering.patch debian/tests-Disable-restore-size-test.patch -ubuntu/x11-Add-support-for-fractional-scaling-using-Randr.patch workspace-Don-t-crash-on-invalid-argument-to-meta_workspa.patch debian/Mark-xwayland-test-case-as-known-to-be-flaky-on-32-bit-AR.patch cursor-renderer-native-Workaround-broken-arm64-drivers.patch -ubuntu/window-Add-ability-to-override-the-edge-constraints.patch -backends-x11-Trap-errors-from-XIChangeProperty.patch display-Set-compositor-selection-earlier-on-XWayland.patch +ubuntu/x11-Add-support-for-fractional-scaling-using-Randr.patch +ubuntu/window-Add-ability-to-override-the-edge-constraints.patch diff -Nru mutter-44.0/debian/patches/tests-Use-a-more-interoperable-path-to-bash.patch mutter-44.1/debian/patches/tests-Use-a-more-interoperable-path-to-bash.patch --- mutter-44.0/debian/patches/tests-Use-a-more-interoperable-path-to-bash.patch 2023-04-18 20:44:57.000000000 +0000 +++ mutter-44.1/debian/patches/tests-Use-a-more-interoperable-path-to-bash.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,70 +0,0 @@ -From: Simon McVittie -Date: Mon, 6 Mar 2023 10:32:55 +0000 -Subject: tests: Use a more interoperable path to bash - -On systems that have undergone the /usr merge, /bin/bash and -/usr/bin/bash can be used interchangeably, but on systems where /bin and -/usr/bin are separate (such as Debian 11 or older), bash was traditionally -in /bin and there is no bash in /usr/bin. - -Bug: https://gitlab.gnome.org/GNOME/mutter/-/issues/2385 -Signed-off-by: Simon McVittie -Forwarded: https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2900 ---- - .gitlab-ci/checkout-gnome-shell.sh | 2 +- - .gitlab-ci/download-coverity-tarball.sh | 2 +- - src/tests/kvm/run-kvm-test.sh | 2 +- - src/tests/kvm/virtme-run.sh | 2 +- - src/tests/x11-test.sh | 2 +- - 5 files changed, 5 insertions(+), 5 deletions(-) - -diff --git a/.gitlab-ci/checkout-gnome-shell.sh b/.gitlab-ci/checkout-gnome-shell.sh -index e4bb9c4..4e086da 100755 ---- a/.gitlab-ci/checkout-gnome-shell.sh -+++ b/.gitlab-ci/checkout-gnome-shell.sh -@@ -1,4 +1,4 @@ --#!/usr/bin/bash -+#!/bin/bash - - fetch() { - local remote=$1 -diff --git a/.gitlab-ci/download-coverity-tarball.sh b/.gitlab-ci/download-coverity-tarball.sh -index ca875c9..182363c 100755 ---- a/.gitlab-ci/download-coverity-tarball.sh -+++ b/.gitlab-ci/download-coverity-tarball.sh -@@ -1,4 +1,4 @@ --#!/usr/bin/bash -+#!/bin/bash - - # We need a coverity token to fetch the tarball - if [ -x $COVERITY_TOKEN ] -diff --git a/src/tests/kvm/run-kvm-test.sh b/src/tests/kvm/run-kvm-test.sh -index ff94a68..4213ef9 100755 ---- a/src/tests/kvm/run-kvm-test.sh -+++ b/src/tests/kvm/run-kvm-test.sh -@@ -1,4 +1,4 @@ --#!/usr/bin/bash -+#!/bin/bash - - set -e - -diff --git a/src/tests/kvm/virtme-run.sh b/src/tests/kvm/virtme-run.sh -index 836b383..d079654 100755 ---- a/src/tests/kvm/virtme-run.sh -+++ b/src/tests/kvm/virtme-run.sh -@@ -1,4 +1,4 @@ --#!/usr/bin/bash -+#!/bin/bash - - set -e - -diff --git a/src/tests/x11-test.sh b/src/tests/x11-test.sh -index 376a019..59e460f 100755 ---- a/src/tests/x11-test.sh -+++ b/src/tests/x11-test.sh -@@ -1,4 +1,4 @@ --#!/usr/bin/bash -+#!/bin/bash - - set -e - diff -Nru mutter-44.0/.gitlab-ci/checkout-gnome-shell.sh mutter-44.1/.gitlab-ci/checkout-gnome-shell.sh --- mutter-44.0/.gitlab-ci/checkout-gnome-shell.sh 2023-03-19 10:55:05.000000000 +0000 +++ mutter-44.1/.gitlab-ci/checkout-gnome-shell.sh 2023-04-25 16:16:17.000000000 +0000 @@ -1,4 +1,4 @@ -#!/usr/bin/bash +#!/bin/bash fetch() { local remote=$1 diff -Nru mutter-44.0/.gitlab-ci/download-coverity-tarball.sh mutter-44.1/.gitlab-ci/download-coverity-tarball.sh --- mutter-44.0/.gitlab-ci/download-coverity-tarball.sh 2023-03-19 10:55:05.000000000 +0000 +++ mutter-44.1/.gitlab-ci/download-coverity-tarball.sh 2023-04-25 16:16:17.000000000 +0000 @@ -1,4 +1,4 @@ -#!/usr/bin/bash +#!/bin/bash # We need a coverity token to fetch the tarball if [ -x $COVERITY_TOKEN ] diff -Nru mutter-44.0/meson.build mutter-44.1/meson.build --- mutter-44.0/meson.build 2023-03-19 10:55:05.000000000 +0000 +++ mutter-44.1/meson.build 2023-04-25 16:16:17.000000000 +0000 @@ -1,5 +1,5 @@ project('mutter', 'c', - version: '44.0', + version: '44.1', meson_version: '>= 0.58.0', license: 'GPLv2+' ) @@ -212,6 +212,7 @@ if have_wayland wayland_server_dep = dependency('wayland-server', version: wayland_server_req) wayland_client_dep = dependency('wayland-client', version: wayland_server_req) + wayland_cursor_dep = dependency('wayland-cursor') wayland_protocols_dep = dependency('wayland-protocols', version: wayland_protocols_req) wayland_egl_dep = dependency('wayland-egl') diff -Nru mutter-44.0/NEWS mutter-44.1/NEWS --- mutter-44.0/NEWS 2023-03-19 10:55:05.000000000 +0000 +++ mutter-44.1/NEWS 2023-04-25 16:16:17.000000000 +0000 @@ -1,3 +1,36 @@ +44.1 +==== +* Fall back to the default, not the unknown color space [Sebastian W.; !2915] +* Fix resizing windows via keyboard [Florian; !2908] +* Fix possible screen freeze after resume with multiple monitors [Daniel; !2933] +* Fix anchor position when dragging window [Carlos; !2942] +* Fix applying XSettings to decorations on X11 [Marco; !2948] +* Allow clipped redraws for headless backend [Salman; !2775] +* Improve screencast support [Georges; !2804] +* Fix focus-on-click for server-side decorated windows [Carlos; !2954] +* Fix initial fullscreen state of server-side decorated windows [Carlos; !2961] +* Fix feedback loop triggering bursts of excessive CPU load [Robert; !2823] +* Enable modifiers by default on non-native backend [Robert; !2972] +* Check EDID for supported sink Colorimetry [Sebastian W.; !2919] +* Fix artifacts in titlebars on some hardware [Carlos; !2976] +* Fix map transitions for X11 windows on wayland [Carlos; !2975] +* Fixed crashes [Jonas Å., Sebastian K., Carlos, Michel, Daniel, Robert; + !2932, !2930, !2945, !2956, !2962, !2968, !2967, !2960, !2963] +* Plugged leaks [Sebastian K., Jonas Å.; !2922, !2926, !2957] +* Misc. bug fixes and cleanups [Daniel, Ivan, Emmanuele, Simon, Jonas D., + Jonas Å., Chris, Florian, Corentin, msizanoen1, Sebastian K.; !2918, !2904, + !2928, !2929, !2900, !2856, !2944, !2935, !2947, !2949, !2951, !2940, !2953, + !2964, !2934, !2902, !2971] + +Contributors: + Jonas Ådahl, Emmanuele Bassi, Michel Dänzer, Jonas Dreßler, Carlos Garnacho, + Sebastian Keller, Robert Mader, Chris Mayo, Simon McVittie, Ivan Molodetskikh, + msizanoen1, Florian Müllner, Georges Basile Stavracas Neto, Corentin Noël, + Salman, Marco Trevisan (Treviño), Daniel van Vugt, Sebastian Wick + +Translators: + Boyuan Yang [zh_CN], Ngọc Quân Trần [vi], Nathan Follens [nl] + 44.0 ==== * Fix state confusion and delay on startup [Carlos; !2906] diff -Nru mutter-44.0/po/nl.po mutter-44.1/po/nl.po --- mutter-44.0/po/nl.po 2023-03-19 10:55:05.000000000 +0000 +++ mutter-44.1/po/nl.po 2023-04-25 16:16:17.000000000 +0000 @@ -5,22 +5,22 @@ # Michiel Sikkes , 2005. # Wouter Bolsterlee , 2006–2012. # Hannie Dumoleyn , 2016. -# Nathan Follens , 2017, 2019-2022. +# Nathan Follens , 2017, 2019-2023. msgid "" msgstr "" "Project-Id-Version: mutter\n" "Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/mutter/issues\n" -"POT-Creation-Date: 2022-09-02 08:42+0000\n" -"PO-Revision-Date: 2022-11-02 00:43+0100\n" +"POT-Creation-Date: 2023-03-21 14:03+0000\n" +"PO-Revision-Date: 2023-04-02 15:04+0200\n" "Last-Translator: Nathan Follens \n" -"Language-Team: Dutch \n" +"Language-Team: Dutch https://matrix.to/#/#nl:gnome.org\n" "Language: nl\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" "X-Project-Style: gnome\n" -"X-Generator: Poedit 3.1.1\n" +"X-Generator: Poedit 3.2.2\n" #: data/50-mutter-navigation.xml:6 msgid "Navigation" @@ -250,18 +250,14 @@ msgid "Maximize window horizontally" msgstr "Venster horizontaal maximaliseren" -#: data/50-mutter-windows.xml:41 data/org.gnome.mutter.gschema.xml.in:173 +#: data/50-mutter-windows.xml:41 data/org.gnome.mutter.gschema.xml.in:164 msgid "View split on left" msgstr "Weergave gesplitst op links" -#: data/50-mutter-windows.xml:45 data/org.gnome.mutter.gschema.xml.in:178 +#: data/50-mutter-windows.xml:45 data/org.gnome.mutter.gschema.xml.in:169 msgid "View split on right" msgstr "Weergave gesplitst op rechts" -#: data/mutter.desktop.in:4 -msgid "Mutter" -msgstr "Mutter" - #: data/org.gnome.mutter.gschema.xml.in:15 msgid "Modifier to use for extended window management operations" msgstr "Controletoets voor uitgebreide vensterbeheerfunctionaliteit" @@ -334,22 +330,10 @@ "voor vensters op het hoofdscherm moet gebeuren." #: data/org.gnome.mutter.gschema.xml.in:67 -msgid "No tab popup" -msgstr "Geen tab-pop-up" - -#: data/org.gnome.mutter.gschema.xml.in:68 -msgid "" -"Determines whether the use of popup and highlight frame should be disabled " -"for window cycling." -msgstr "" -"Bepaalt of het gebruik van pop-up en markering van het kader uitgeschakeld " -"wordt voor het vensterbladeren." - -#: data/org.gnome.mutter.gschema.xml.in:76 msgid "Delay focus changes until the pointer stops moving" msgstr "Aandacht vertragen totdat de muispijl stopt met bewegen" -#: data/org.gnome.mutter.gschema.xml.in:77 +#: data/org.gnome.mutter.gschema.xml.in:68 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 " @@ -359,11 +343,11 @@ "‘mouse’, dan zal de aandacht niet direct veranderd worden bij het binnengaan " "van een venster, maar slechts wanneer de muispijl stopt met bewegen." -#: data/org.gnome.mutter.gschema.xml.in:87 +#: data/org.gnome.mutter.gschema.xml.in:78 msgid "Draggable border width" msgstr "Sleepbare randbreedte" -#: data/org.gnome.mutter.gschema.xml.in:88 +#: data/org.gnome.mutter.gschema.xml.in:79 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." @@ -372,11 +356,11 @@ "onvoldoende zijn, worden onzichtbare randen toegevoegd om deze waarde te " "bereiken." -#: data/org.gnome.mutter.gschema.xml.in:97 +#: data/org.gnome.mutter.gschema.xml.in:88 msgid "Auto maximize nearly monitor sized windows" msgstr "Vensters van bijna-monitorformaat auto-maximaliseren" -#: data/org.gnome.mutter.gschema.xml.in:98 +#: data/org.gnome.mutter.gschema.xml.in:89 msgid "" "If enabled, new windows that are initially the size of the monitor " "automatically get maximized." @@ -384,11 +368,11 @@ "Indien ingeschakeld, worden vensters die initieel ongeveer even groot zijn " "als de monitor automatisch gemaximaliseerd." -#: data/org.gnome.mutter.gschema.xml.in:106 +#: data/org.gnome.mutter.gschema.xml.in:97 msgid "Place new windows in the center" msgstr "Plaats nieuwe vensters in het midden" -#: data/org.gnome.mutter.gschema.xml.in:107 +#: data/org.gnome.mutter.gschema.xml.in:98 msgid "" "When true, the new windows will always be put in the center of the active " "screen of the monitor." @@ -396,11 +380,11 @@ "Indien waar zullen nieuwe vensters steeds in het midden van het actieve " "scherm van de monitor geplaatst worden." -#: data/org.gnome.mutter.gschema.xml.in:116 +#: data/org.gnome.mutter.gschema.xml.in:107 msgid "Enable experimental features" msgstr "Experimentele functies inschakelen" -#: data/org.gnome.mutter.gschema.xml.in:117 +#: data/org.gnome.mutter.gschema.xml.in:108 msgid "" "To enable experimental features, add the feature keyword to the list. " "Whether the feature requires restarting the compositor depends on the given " @@ -433,19 +417,19 @@ "“autoclose-xwayland” — beëindigt Xwayland automatisch wanneer er geen " "relevante X11-cliënten meer zijn. Hiervoor is opnieuw opstarten vereist." -#: data/org.gnome.mutter.gschema.xml.in:150 +#: data/org.gnome.mutter.gschema.xml.in:141 msgid "Modifier to use to locate the pointer" msgstr "Controletoets om de muispijl te lokaliseren" -#: data/org.gnome.mutter.gschema.xml.in:151 +#: data/org.gnome.mutter.gschema.xml.in:142 msgid "This key will initiate the “locate pointer” action." msgstr "Deze sleutel activeert de actie ‘muispijl lokaliseren’." -#: data/org.gnome.mutter.gschema.xml.in:158 +#: data/org.gnome.mutter.gschema.xml.in:149 msgid "Timeout for check-alive ping" msgstr "Time-out voor levenscontroleping" -#: data/org.gnome.mutter.gschema.xml.in:159 +#: data/org.gnome.mutter.gschema.xml.in:150 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." @@ -454,19 +438,11 @@ "verzoek om niet als bevroren beschouwd te worden. Stel dit in op 0 om de " "levenscontrole volledig uit te schakelen." -#: data/org.gnome.mutter.gschema.xml.in:183 -msgid "Select window from tab popup" -msgstr "Venster selecteren uit tab-pop-up" - -#: data/org.gnome.mutter.gschema.xml.in:188 -msgid "Cancel tab popup" -msgstr "Tab-pop-up annuleren" - -#: data/org.gnome.mutter.gschema.xml.in:193 +#: data/org.gnome.mutter.gschema.xml.in:174 msgid "Switch monitor configurations" msgstr "Tussen beeldschermconfiguraties schakelen" -#: data/org.gnome.mutter.gschema.xml.in:198 +#: data/org.gnome.mutter.gschema.xml.in:179 msgid "Rotates the built-in monitor configuration" msgstr "Roteert de ingebouwde beeldschermconfiguratie" @@ -597,6 +573,34 @@ "voor de geselecteerde uitbreidingen. Deze instellingen treedt pas in werking " "wanneer Xwayland wordt herstart." +#: data/org.gnome.mutter.wayland.gschema.xml.in:130 +msgid "Allow X11 clients with a different endianness to connect to Xwayland" +msgstr "" +"X11-cliënten met verschillende endianness toestaan te verbinden met Xwayland" + +#: data/org.gnome.mutter.wayland.gschema.xml.in:131 +msgid "" +"Allow connections from clients with an endianness different to that of " +"Xwayland. The X server byte-swapping code is a huge attack surface, much of " +"that code in Xwayland is prone to security issues. The use-case of byte-" +"swapped clients is very niche, and disabled by default in Xwayland. Enable " +"this option to instruct Xwayland to accept connections from X11 clients with " +"a different endianness. This option has no effect if Xwayland does not " +"support the command line option +byteswappedclients/-byteswappedclients to " +"control that setting. Xwayland needs to be restarted for this setting to " +"take effect." +msgstr "" +"Sta verbindingen toe van cliënten met een endianness die verschilt van die " +"van Xwayland. De byteswappingcode van de X-server is een enorm " +"aanvalsoppervlak, en veel van die code in Xwayland is gevoelig voor " +"beveiligingsproblemen. Byteswapped cliënten worden maar in heel niche " +"gevallen toegepast, en het gebruik ervan is standaard uitgeschakeld in " +"Xwayland. Schakel deze optie in om Xwayland verbindingen van X11-cliënten " +"met een verschillende endianness te laten aanvaarden. Deze optie doet niets " +"als Xwayland geen ondersteuning biedt voor de opdrachtregeloptie " +"+byteswappedclients/-byteswappedclients om die instelling te beheren. " +"Xwayland moet herstart worden om deze instelling toe te passen." + #: src/backends/meta-monitor.c:253 msgid "Built-in display" msgstr "Ingebouwd beeldscherm" @@ -624,14 +628,9 @@ msgid "%s %s" msgstr "%s %s" -#. Translators: this string will appear in Sysprof -#: 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:400 +#: src/compositor/compositor.c:416 #, c-format msgid "" "Another compositing manager is already running on screen %i on display “%s”." @@ -643,74 +642,74 @@ msgid "Bell event" msgstr "Bel-gebeurtenis" -#: src/core/display.c:693 +#: src/core/display.c:703 msgid "Privacy Screen Enabled" msgstr "Privacyscherm ingeschakeld" -#: src/core/display.c:694 +#: src/core/display.c:704 msgid "Privacy Screen Disabled" msgstr "Privacyscherm uitgeschakeld" -#: src/core/meta-context-main.c:567 +#: src/core/meta-context-main.c:579 msgid "Replace the running window manager" msgstr "De huidige toepassing voor vensterbeheer vervangen" -#: src/core/meta-context-main.c:573 +#: src/core/meta-context-main.c:585 msgid "X Display to use" msgstr "De te gebruiken X-weergave" -#: src/core/meta-context-main.c:579 +#: src/core/meta-context-main.c:591 msgid "Disable connection to session manager" msgstr "Schakel de verbinding met het sessiebeheer uit" -#: src/core/meta-context-main.c:585 +#: src/core/meta-context-main.c:597 msgid "Specify session management ID" msgstr "Bepaal de ID van het sessiebeheer" -#: src/core/meta-context-main.c:591 +#: src/core/meta-context-main.c:603 msgid "Initialize session from savefile" msgstr "Initialiseer de sessie middels een opslagbestand" -#: src/core/meta-context-main.c:597 +#: src/core/meta-context-main.c:609 msgid "Make X calls synchronous" msgstr "X-aanroepen synchroon maken" -#: src/core/meta-context-main.c:605 +#: src/core/meta-context-main.c:617 msgid "Run as a wayland compositor" msgstr "Uitvoeren als een wayland compositor" -#: src/core/meta-context-main.c:611 +#: src/core/meta-context-main.c:623 msgid "Run as a nested compositor" msgstr "Uitvoeren als een geneste compositor" -#: src/core/meta-context-main.c:617 +#: src/core/meta-context-main.c:629 msgid "Run wayland compositor without starting Xwayland" msgstr "Wayland-compositor uitvoeren zonder Xwayland te starten" -#: src/core/meta-context-main.c:623 +#: src/core/meta-context-main.c:635 msgid "Specify Wayland display name to use" msgstr "Bepaal de te gebruiken Wayland-weergavenaam" -#: src/core/meta-context-main.c:631 +#: src/core/meta-context-main.c:643 msgid "Run as a full display server, rather than nested" msgstr "Uitvoeren als een volledige displayserver, in plaats van genest" -#: src/core/meta-context-main.c:636 +#: src/core/meta-context-main.c:648 msgid "Run as a headless display server" msgstr "Uitvoeren als een ‘headless’ displayserver" -#: src/core/meta-context-main.c:641 +#: src/core/meta-context-main.c:653 msgid "Add persistent virtual monitor (WxH or WxH@R)" msgstr "Blijvend virtueel beeldscherm toevoegen (BxH of BxH@V)" -#: src/core/meta-context-main.c:653 +#: src/core/meta-context-main.c:665 msgid "Run with X11 backend" msgstr "Uitvoeren met X11-backend" #. TRANSLATORS: This string refers to a button that switches between #. * different modes. #. -#: src/core/meta-pad-action-mapper.c:848 +#: src/core/meta-pad-action-mapper.c:861 #, c-format msgid "Mode Switch (Group %d)" msgstr "Moduswisselaar (groep %d)" @@ -718,14 +717,19 @@ #. TRANSLATORS: This string refers to an action, cycles drawing tablets' #. * mapping through the available outputs. #. -#: src/core/meta-pad-action-mapper.c:871 +#: src/core/meta-pad-action-mapper.c:884 msgid "Switch monitor" msgstr "Van beeldscherm wisselen" -#: src/core/meta-pad-action-mapper.c:873 +#: src/core/meta-pad-action-mapper.c:886 msgid "Show on-screen help" msgstr "Hulptekst op scherm tonen" +#. Translators: this string will appear in Sysprof +#: src/core/meta-profiler.c:80 src/core/meta-profiler.c:217 +msgid "Compositor" +msgstr "Compositor" + #: src/core/mutter.c:74 msgid "Print version" msgstr "Versie-informatie tonen" @@ -739,20 +743,20 @@ msgid "Workspace %d" msgstr "Werkblad %d" -#: src/core/util.c:143 +#: src/core/util.c:142 msgid "Mutter was compiled without support for verbose mode" msgstr "Mutter is gecompileerd zonder ondersteuning voor verbose-mode" -#: src/core/workspace.c:533 +#: src/core/workspace.c:541 msgid "Workspace switched" msgstr "Werkblad gewisseld" -#: src/wayland/meta-wayland-tablet-pad.c:520 +#: src/wayland/meta-wayland-tablet-pad.c:530 #, c-format msgid "Mode Switch: Mode %d" msgstr "Moduswisselaar: modus %d" -#: src/x11/meta-x11-display.c:659 +#: src/x11/meta-x11-display.c:701 #, c-format msgid "" "Display “%s” already has a window manager; try using the --replace option to " @@ -761,30 +765,48 @@ "Beeldscherm ‘%s’ heeft al een vensterbeheerder; probeer de optie: --replace " "te gebruiken om de huidige vensterbeheerder te vervangen." -#: src/x11/meta-x11-display.c:1053 -msgid "Failed to initialize GDK" -msgstr "Initialiseren van GDK mislukt" - -#: src/x11/meta-x11-display.c:1080 +#: src/x11/meta-x11-display.c:1062 #, c-format msgid "Failed to open X Window System display “%s”" msgstr "Openen van X Window System display ‘%s’ mislukt" -#: src/x11/meta-x11-display.c:1188 +#: src/x11/meta-x11-display.c:1207 #, c-format msgid "Screen %d on display “%s” is invalid" msgstr "Scherm %d op beeldscherm ‘%s’ is ongeldig" -#: src/x11/meta-x11-selection-input-stream.c:474 +#: src/x11/meta-x11-selection-input-stream.c:481 #, c-format msgid "Format %s not supported" msgstr "Formaat %s wordt niet ondersteund" -#: src/x11/window-props.c:548 +#: src/x11/window-props.c:549 #, c-format msgid "%s (on %s)" msgstr "%s (op %s)" +#~ msgid "Mutter" +#~ msgstr "Mutter" + +#~ msgid "No tab popup" +#~ msgstr "Geen tab-pop-up" + +#~ msgid "" +#~ "Determines whether the use of popup and highlight frame should be " +#~ "disabled for window cycling." +#~ msgstr "" +#~ "Bepaalt of het gebruik van pop-up en markering van het kader " +#~ "uitgeschakeld wordt voor het vensterbladeren." + +#~ msgid "Select window from tab popup" +#~ msgstr "Venster selecteren uit tab-pop-up" + +#~ msgid "Cancel tab popup" +#~ msgstr "Tab-pop-up annuleren" + +#~ msgid "Failed to initialize GDK" +#~ msgstr "Initialiseren van GDK mislukt" + #, c-format #~ msgid "“%s” is not responding." #~ msgstr "‘%s’ reageert niet." @@ -1383,8 +1405,8 @@ #~ msgstr "Element <%s> is niet toegestaan onder <%s>" #~ msgid "" -#~ "Cannot specify both \"button_width\"/\"button_height\" and \"aspect_ratio" -#~ "\" for buttons" +#~ "Cannot specify both \"button_width\"/\"button_height\" and " +#~ "\"aspect_ratio\" for buttons" #~ msgstr "" #~ "Kan niet tegelijk ‘button_width’/‘button_height’ en ‘aspect_ratio’ voor " #~ "knoppen opgeven." diff -Nru mutter-44.0/po/vi.po mutter-44.1/po/vi.po --- mutter-44.0/po/vi.po 2023-03-19 10:55:05.000000000 +0000 +++ mutter-44.1/po/vi.po 2023-04-25 16:16:17.000000000 +0000 @@ -9,8 +9,8 @@ msgstr "" "Project-Id-Version: mutter main\n" "Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/mutter/issues\n" -"POT-Creation-Date: 2022-03-31 13:03+0000\n" -"PO-Revision-Date: 2022-04-04 07:38+0700\n" +"POT-Creation-Date: 2023-03-30 11:40+0000\n" +"PO-Revision-Date: 2023-04-01 08:20+0700\n" "Last-Translator: Trần Ngọc Quân \n" "Language-Team: Vietnamese \n" "Language: vi\n" @@ -248,18 +248,14 @@ msgid "Maximize window horizontally" msgstr "Phóng to cửa sổ theo chiều ngang" -#: data/50-mutter-windows.xml:41 data/org.gnome.mutter.gschema.xml.in:173 +#: data/50-mutter-windows.xml:41 data/org.gnome.mutter.gschema.xml.in:164 msgid "View split on left" msgstr "Phân đôi bên trái" -#: data/50-mutter-windows.xml:45 data/org.gnome.mutter.gschema.xml.in:178 +#: data/50-mutter-windows.xml:45 data/org.gnome.mutter.gschema.xml.in:169 msgid "View split on right" msgstr "Phân đôi bên phải" -#: data/mutter.desktop.in:4 -msgid "Mutter" -msgstr "Mutter" - #: data/org.gnome.mutter.gschema.xml.in:15 msgid "Modifier to use for extended window management operations" msgstr "Phím bổ trợ dùng cho chức năng quản lý cửa sổ mở rộng" @@ -330,20 +326,10 @@ "trên màn hình chính." #: data/org.gnome.mutter.gschema.xml.in:67 -msgid "No tab popup" -msgstr "Không tab popup" - -#: data/org.gnome.mutter.gschema.xml.in:68 -msgid "" -"Determines whether the use of popup and highlight frame should be disabled " -"for window cycling." -msgstr "Xác định có bỏ qua popup và khung tô sáng khi xoay vòng cửa sổ không." - -#: data/org.gnome.mutter.gschema.xml.in:76 msgid "Delay focus changes until the pointer stops moving" msgstr "Khoảng chờ con trỏ dừng di chuyển trước khi thay đổi tiêu điểm" -#: data/org.gnome.mutter.gschema.xml.in:77 +#: data/org.gnome.mutter.gschema.xml.in:68 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 " @@ -353,11 +339,11 @@ "không thay đổi tức thì khi vào cửa sổ, mà chỉ sau khi con trỏ ngừng di " "chuyển." -#: data/org.gnome.mutter.gschema.xml.in:87 +#: data/org.gnome.mutter.gschema.xml.in:78 msgid "Draggable border width" msgstr "Độ rộng biên có thể kéo" -#: data/org.gnome.mutter.gschema.xml.in:88 +#: data/org.gnome.mutter.gschema.xml.in:79 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." @@ -365,21 +351,21 @@ "Kích thước biên có thể kéo. Nếu biên thấy được của chủ đề không đủ, biên vô " "hình sẽ được thêm vào để thỏa mãn giá trị này." -#: data/org.gnome.mutter.gschema.xml.in:97 +#: data/org.gnome.mutter.gschema.xml.in:88 msgid "Auto maximize nearly monitor sized windows" msgstr "Tự động phóng to cửa sổ gần bằng màn hình" -#: data/org.gnome.mutter.gschema.xml.in:98 +#: data/org.gnome.mutter.gschema.xml.in:89 msgid "" "If enabled, new windows that are initially the size of the monitor " "automatically get maximized." msgstr "Nếu bật, sẽ tự động phóng to cửa sổ mới với kích thước tối đa." -#: data/org.gnome.mutter.gschema.xml.in:106 +#: data/org.gnome.mutter.gschema.xml.in:97 msgid "Place new windows in the center" msgstr "Đặt cửa sổ mới ở chính giữa" -#: data/org.gnome.mutter.gschema.xml.in:107 +#: data/org.gnome.mutter.gschema.xml.in:98 msgid "" "When true, the new windows will always be put in the center of the active " "screen of the monitor." @@ -387,11 +373,11 @@ "Nếu chọn, các cửa sổ mới sẽ luôn được đặt tại trung tâm của màn hình đang " "hoạt động của màn hình." -#: data/org.gnome.mutter.gschema.xml.in:116 +#: data/org.gnome.mutter.gschema.xml.in:107 msgid "Enable experimental features" msgstr "Bật các tính băng thử nghiệm" -#: data/org.gnome.mutter.gschema.xml.in:117 +#: data/org.gnome.mutter.gschema.xml.in:108 msgid "" "To enable experimental features, add the feature keyword to the list. " "Whether the feature requires restarting the compositor depends on the given " @@ -422,19 +408,19 @@ "khởi động lại. • “autoclose-xwayland” — tự động chấm dứt Xwayland nếu mọi " "trình khách ra đi. Không yêu cầu khởi động lại." -#: data/org.gnome.mutter.gschema.xml.in:150 +#: data/org.gnome.mutter.gschema.xml.in:141 msgid "Modifier to use to locate the pointer" msgstr "Chỉnh sửa để dùng để định vị con trỏ" -#: data/org.gnome.mutter.gschema.xml.in:151 +#: data/org.gnome.mutter.gschema.xml.in:142 msgid "This key will initiate the “locate pointer” action." msgstr "Khóa này sẽ khởi tạo thao tác “định vị con trỏ”." -#: data/org.gnome.mutter.gschema.xml.in:158 +#: data/org.gnome.mutter.gschema.xml.in:149 msgid "Timeout for check-alive ping" msgstr "Thời gian chờ để kiểm tra ping còn sống" -#: data/org.gnome.mutter.gschema.xml.in:159 +#: data/org.gnome.mutter.gschema.xml.in:150 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." @@ -442,19 +428,11 @@ "Số mili giây mà máy khách phải trả lời yêu cầu ping để không bị cho là đang " "ngủ đông. Sử dụng 0 sẽ vô hiệu hóa kiểm tra sống." -#: data/org.gnome.mutter.gschema.xml.in:183 -msgid "Select window from tab popup" -msgstr "Chọn cửa sổ từ thanh nổi lên" - -#: data/org.gnome.mutter.gschema.xml.in:188 -msgid "Cancel tab popup" -msgstr "Hủy thanh nổi lên" - -#: data/org.gnome.mutter.gschema.xml.in:193 +#: data/org.gnome.mutter.gschema.xml.in:174 msgid "Switch monitor configurations" msgstr "Chuyển các cấu hình màn hình" -#: data/org.gnome.mutter.gschema.xml.in:198 +#: data/org.gnome.mutter.gschema.xml.in:179 msgid "Rotates the built-in monitor configuration" msgstr "Quay cấu hình màn hình tích hợp" @@ -581,26 +559,51 @@ "không có tác dụng nếu Xwayland được biên dịch mà không hỗ trợ các phần mở " "rộng đã chọn. Xwayland cần được khởi động lại để cài đặt này có hiệu lực." -#: src/backends/meta-monitor.c:246 +#: data/org.gnome.mutter.wayland.gschema.xml.in:130 +msgid "Allow X11 clients with a different endianness to connect to Xwayland" +msgstr "Cho phép các máy khách X11 có endianness khác kết nối với Xwayland" + +#: data/org.gnome.mutter.wayland.gschema.xml.in:131 +msgid "" +"Allow connections from clients with an endianness different to that of " +"Xwayland. The X server byte-swapping code is a huge attack surface, much of " +"that code in Xwayland is prone to security issues. The use-case of byte-" +"swapped clients is very niche, and disabled by default in Xwayland. Enable " +"this option to instruct Xwayland to accept connections from X11 clients with " +"a different endianness. This option has no effect if Xwayland does not " +"support the command line option +byteswappedclients/-byteswappedclients to " +"control that setting. Xwayland needs to be restarted for this setting to " +"take effect." +msgstr "" +"Cho phép các kết nối từ các máy khách có endianness khác với Xwayland. Mã " +"hoán đổi byte của máy chủ X là một bề mặt tấn công lớn, phần lớn mã đó trong " +"Xwayland dễ gặp sự cố bảo mật. Trường hợp sử dụng của các ứng dụng khách " +"hoán đổi byte rất thích hợp và bị tắt theo mặc định trong Xwayland. Bật tùy " +"chọn này để hướng dẫn Xwayland chấp nhận các kết nối từ các máy khách X11 có " +"endianness khác nhau. Tùy chọn này không có tác dụng nếu Xwayland không hỗ " +"trợ tùy chọn dòng lệnh +byteswappedclients/-byteswappedclients để kiểm soát " +"cài đặt đó. Xwayland cần được khởi động lại để cài đặt này có hiệu lực." + +#: src/backends/meta-monitor.c:253 msgid "Built-in display" msgstr "Màn hình tích hợp" -#: src/backends/meta-monitor.c:275 +#: src/backends/meta-monitor.c:280 msgid "Unknown" msgstr "Không rõ" -#: src/backends/meta-monitor.c:277 +#: src/backends/meta-monitor.c:282 msgid "Unknown Display" msgstr "Không hiểu màn hình" -#: src/backends/meta-monitor.c:285 +#: src/backends/meta-monitor.c:290 #, 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:293 +#: src/backends/meta-monitor.c:298 #, c-format msgctxt "" "This is a monitor vendor name followed by product/model name where size in " @@ -608,14 +611,9 @@ msgid "%s %s" msgstr "%s %s" -#. Translators: this string will appear in Sysprof -#: src/backends/meta-profiler.c:79 -msgid "Compositor" -msgstr "Bộ tổng hợp" - #. 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:392 +#: src/compositor/compositor.c:416 #, c-format msgid "" "Another compositing manager is already running on screen %i on display “%s”." @@ -625,100 +623,74 @@ msgid "Bell event" msgstr "Sự kiện chuông" -#: src/core/display.c:687 +#: src/core/display.c:703 msgid "Privacy Screen Enabled" msgstr "Màn hình riêng tư được bật" -#: src/core/display.c:688 +#: src/core/display.c:704 msgid "Privacy Screen Disabled" msgstr "Màn hình riêng tư bị bật" -#. Translators: %s is a window title -#: src/core/meta-close-dialog-default.c:151 -#, c-format -msgid "“%s” is not responding." -msgstr "“%s” không phản ứng." - -#: src/core/meta-close-dialog-default.c:153 -msgid "Application is not responding." -msgstr "Ứng dụng không phản ứng gì." - -#: 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 "" -"Bạn có thể chọn chờ một lát để nó có thể tiếp tục chạy hoặc buộc chấm dứt " -"hoàn toàn ứng dụng." - -#: src/core/meta-close-dialog-default.c:164 -msgid "_Force Quit" -msgstr "_Buộc thoát" - -#: src/core/meta-close-dialog-default.c:164 -msgid "_Wait" -msgstr "_Chờ" - -#: src/core/meta-context-main.c:555 +#: src/core/meta-context-main.c:579 msgid "Replace the running window manager" msgstr "Thay thế bộ quản lý cửa sổ đang chạy" -#: src/core/meta-context-main.c:561 +#: src/core/meta-context-main.c:585 msgid "X Display to use" msgstr "Màn hình X cần dùng" -#: src/core/meta-context-main.c:567 +#: src/core/meta-context-main.c:591 msgid "Disable connection to session manager" msgstr "Vô hiệu hóa kết nối với bộ quản lý phiên làm việc" -#: src/core/meta-context-main.c:573 +#: src/core/meta-context-main.c:597 msgid "Specify session management ID" msgstr "Ghi rõ mã số quản lý phiên làm việc" -#: src/core/meta-context-main.c:579 +#: src/core/meta-context-main.c:603 msgid "Initialize session from savefile" msgstr "Khởi động phiên làm việc từ tập tin lưu" -#: src/core/meta-context-main.c:585 +#: src/core/meta-context-main.c:609 msgid "Make X calls synchronous" msgstr "Khiến các cú gọi X đồng bộ" -#: src/core/meta-context-main.c:592 +#: src/core/meta-context-main.c:617 msgid "Run as a wayland compositor" msgstr "Chạy như là một “bộ tổng hợp wayland”" -#: src/core/meta-context-main.c:598 +#: src/core/meta-context-main.c:623 msgid "Run as a nested compositor" msgstr "Chạy như là một “bộ tổng hợp lồng nhau”" -#: src/core/meta-context-main.c:604 +#: src/core/meta-context-main.c:629 msgid "Run wayland compositor without starting Xwayland" msgstr "Chạy bộ tổng hợp wayland mà không khởi chạy Xwayland" -#: src/core/meta-context-main.c:610 +#: src/core/meta-context-main.c:635 msgid "Specify Wayland display name to use" msgstr "Chỉ định tên thiết bị hiển thị Wayland muốn dùng" -#: src/core/meta-context-main.c:618 +#: src/core/meta-context-main.c:643 msgid "Run as a full display server, rather than nested" msgstr "Chạy như là một dịch vụ hiển thị đầy đủ, thay cho lồng nhau" -#: src/core/meta-context-main.c:623 +#: src/core/meta-context-main.c:648 msgid "Run as a headless display server" msgstr "Chạy như là một dịch vụ hiển thị không có đầu" -#: src/core/meta-context-main.c:628 +#: src/core/meta-context-main.c:653 msgid "Add persistent virtual monitor (WxH or WxH@R)" msgstr "Thêm màn hình ảo lâu dài (WxH hoặc WxH@R)" -#: src/core/meta-context-main.c:639 +#: src/core/meta-context-main.c:665 msgid "Run with X11 backend" msgstr "Chạy với ứng dụng chạy phía sau X11" #. TRANSLATORS: This string refers to a button that switches between #. * different modes. #. -#: src/core/meta-pad-action-mapper.c:842 +#: src/core/meta-pad-action-mapper.c:861 #, c-format msgid "Mode Switch (Group %d)" msgstr "Chuyển chế độ (Nhóm %d)" @@ -726,14 +698,19 @@ #. TRANSLATORS: This string refers to an action, cycles drawing tablets' #. * mapping through the available outputs. #. -#: src/core/meta-pad-action-mapper.c:865 +#: src/core/meta-pad-action-mapper.c:884 msgid "Switch monitor" msgstr "Chuyển màn hình" -#: src/core/meta-pad-action-mapper.c:867 +#: src/core/meta-pad-action-mapper.c:886 msgid "Show on-screen help" msgstr "Hiển thị trợ giúp trên-màn-hình" +#. Translators: this string will appear in Sysprof +#: src/core/meta-profiler.c:80 src/core/meta-profiler.c:217 +msgid "Compositor" +msgstr "Bộ tổng hợp" + #: src/core/mutter.c:74 msgid "Print version" msgstr "Hiển thị phiên bản" @@ -751,12 +728,16 @@ msgid "Mutter was compiled without support for verbose mode" msgstr "Mutter đã được biên dịch không hỗ trợ chế độ chi tiết" -#: src/wayland/meta-wayland-tablet-pad.c:520 +#: src/core/workspace.c:541 +msgid "Workspace switched" +msgstr "Đã chuyển đổi không gian làm việc" + +#: src/wayland/meta-wayland-tablet-pad.c:530 #, c-format msgid "Mode Switch: Mode %d" msgstr "Chuyển chế độ: Chế độ %d" -#: src/x11/meta-x11-display.c:673 +#: src/x11/meta-x11-display.c:701 #, c-format msgid "" "Display “%s” already has a window manager; try using the --replace option to " @@ -765,38 +746,74 @@ "Màn hình “%s” đã có bộ quản lý cửa sổ rồi; hãy thử dùng tùy chọn --replace " "để thay thế bộ quản lý cửa sổ đang dùng." -#: src/x11/meta-x11-display.c:1067 -msgid "Failed to initialize GDK" -msgstr "Gặp lỗi khi khởi tạo GDK" - -#: src/x11/meta-x11-display.c:1091 +#: src/x11/meta-x11-display.c:1062 #, c-format msgid "Failed to open X Window System display “%s”" msgstr "Gặp lỗi khi mở bộ hiển thị Hệ thống Cửa sổ X “%s”" -#: src/x11/meta-x11-display.c:1200 +#: src/x11/meta-x11-display.c:1207 #, c-format msgid "Screen %d on display “%s” is invalid" msgstr "Màn hình %d trên bộ hiển thị “%s” là không hợp lệ" -#: src/x11/meta-x11-selection-input-stream.c:460 +#: src/x11/meta-x11-selection-input-stream.c:481 #, c-format msgid "Format %s not supported" msgstr "Không hỗ trợ định dạng %s" -#: src/x11/session.c:1823 -msgid "" -"These windows do not support “save current setup” and will have to be " -"restarted manually next time you log in." -msgstr "" -"Những cửa sổ này không hỗ trợ “lưu cài đặt hiện tại” và sẽ phải khởi động " -"lại bằng tay lần kế bạn đăng nhập." - -#: src/x11/window-props.c:548 +#: src/x11/window-props.c:549 #, c-format msgid "%s (on %s)" msgstr "%s (trên %s)" +#~ msgid "Mutter" +#~ msgstr "Mutter" + +#~ msgid "No tab popup" +#~ msgstr "Không tab popup" + +#~ msgid "" +#~ "Determines whether the use of popup and highlight frame should be " +#~ "disabled for window cycling." +#~ msgstr "" +#~ "Xác định có bỏ qua popup và khung tô sáng khi xoay vòng cửa sổ không." + +#~ msgid "Select window from tab popup" +#~ msgstr "Chọn cửa sổ từ thanh nổi lên" + +#~ msgid "Cancel tab popup" +#~ msgstr "Hủy thanh nổi lên" + +#, c-format +#~ msgid "“%s” is not responding." +#~ msgstr "“%s” không phản ứng." + +#~ msgid "Application is not responding." +#~ msgstr "Ứng dụng không phản ứng gì." + +#~ msgid "" +#~ "You may choose to wait a short while for it to continue or force the " +#~ "application to quit entirely." +#~ msgstr "" +#~ "Bạn có thể chọn chờ một lát để nó có thể tiếp tục chạy hoặc buộc chấm dứt " +#~ "hoàn toàn ứng dụng." + +#~ msgid "_Force Quit" +#~ msgstr "_Buộc thoát" + +#~ msgid "_Wait" +#~ msgstr "_Chờ" + +#~ msgid "Failed to initialize GDK" +#~ msgstr "Gặp lỗi khi khởi tạo GDK" + +#~ msgid "" +#~ "These windows do not support “save current setup” and will have to be " +#~ "restarted manually next time you log in." +#~ msgstr "" +#~ "Những cửa sổ này không hỗ trợ “lưu cài đặt hiện tại” và sẽ phải khởi động " +#~ "lại bằng tay lần kế bạn đăng nhập." + #~ msgid "X display to use" #~ msgstr "Màn hình X cần dùng" @@ -895,16 +912,16 @@ #~ "fg[NORMAL] where NORMAL is the state; could not parse \"%s\"" #~ msgstr "" #~ "Lời ghi rõ màu GTK phải có trạng thái nằm trong ngoặc, v.d. “gtk:" -#~ "fg[NORMAL]”, NORMAL (bình thường) là trạng thái; không thể phân tích \"%s" -#~ "\"." +#~ "fg[NORMAL]”, NORMAL (bình thường) là trạng thái; không thể phân tích " +#~ "\"%s\"." #~ msgid "" #~ "GTK color specification must have a close bracket after the state, e.g. " #~ "gtk:fg[NORMAL] where NORMAL is the state; could not parse \"%s\"" #~ msgstr "" #~ "Lời ghi rõ màu GTK phải có dấu đóng ngoặc sau trạng thái, v.d. " -#~ "“fg[NORMAL]”, NORMAL (bình thường) là trạng thái; không thể phân tích \"%s" -#~ "\"." +#~ "“fg[NORMAL]”, NORMAL (bình thường) là trạng thái; không thể phân tích " +#~ "\"%s\"." #~ msgid "Did not understand state \"%s\" in color specification" #~ msgstr "Không hiểu trạng thái \"%s\" trong đặc tả màu." @@ -1124,8 +1141,8 @@ #~ msgstr "Không cho phép phần tử <%s> dưới <%s>." #~ msgid "" -#~ "Cannot specify both \"button_width\"/\"button_height\" and \"aspect_ratio" -#~ "\" for buttons" +#~ "Cannot specify both \"button_width\"/\"button_height\" and " +#~ "\"aspect_ratio\" for buttons" #~ msgstr "" #~ "Không thể xác định cả hai \"button_width\"/\"button_height\" (chiều rộng/" #~ "cao của cái nút) và \"aspect_ratio\" (tỷ lệ hình thể) cho cái nút" @@ -1506,8 +1523,5 @@ #~ msgid "Workspace 1_0" #~ msgstr "Vùng làm việc 1_0" -#~ msgid "Workspace %s%d" -#~ msgstr "Vùng làm việc %s%d" - #~ msgid "Move to Another _Workspace" #~ msgstr "Chuyển sang vùng làm việc _khác" diff -Nru mutter-44.0/po/zh_CN.po mutter-44.1/po/zh_CN.po --- mutter-44.0/po/zh_CN.po 2023-03-19 10:55:05.000000000 +0000 +++ mutter-44.1/po/zh_CN.po 2023-04-25 16:16:17.000000000 +0000 @@ -16,21 +16,22 @@ # liushuyu , 2018. # Dingzhong Chen , 2017-2021. # lumingzh , 2022. +# Nanling , 2023. # msgid "" msgstr "" "Project-Id-Version: mutter master\n" "Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/mutter/issues\n" -"POT-Creation-Date: 2022-09-02 08:42+0000\n" -"PO-Revision-Date: 2022-09-03 17:29-0400\n" -"Last-Translator: Boyuan Yang <073plan@gmail.com>\n" +"POT-Creation-Date: 2023-03-26 12:17+0000\n" +"PO-Revision-Date: 2023-03-27 09:29+0800\n" +"Last-Translator: Nanling \n" "Language-Team: Chinese - China \n" "Language: zh_CN\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=1; plural=0;\n" -"X-Generator: Poedit 3.1.1\n" +"Plural-Forms: nplurals=1; plural=0\n" +"X-Generator: Gtranslator 42.0\n" #: data/50-mutter-navigation.xml:6 msgid "Navigation" @@ -260,18 +261,14 @@ msgid "Maximize window horizontally" msgstr "水平最大化窗口" -#: data/50-mutter-windows.xml:41 data/org.gnome.mutter.gschema.xml.in:173 +#: data/50-mutter-windows.xml:41 data/org.gnome.mutter.gschema.xml.in:164 msgid "View split on left" msgstr "分屏到左侧" -#: data/50-mutter-windows.xml:45 data/org.gnome.mutter.gschema.xml.in:178 +#: data/50-mutter-windows.xml:45 data/org.gnome.mutter.gschema.xml.in:169 msgid "View split on right" msgstr "分屏到右侧" -#: data/mutter.desktop.in:4 -msgid "Mutter" -msgstr "Mutter" - #: data/org.gnome.mutter.gschema.xml.in:15 msgid "Modifier to use for extended window management operations" msgstr "用于扩展窗口管理操作的修饰键" @@ -338,20 +335,10 @@ msgstr "决定工作区切换对所有显示器上的窗口还是只对主显示器上的有效。" #: data/org.gnome.mutter.gschema.xml.in:67 -msgid "No tab popup" -msgstr "无 Tab 轮换弹窗" - -#: data/org.gnome.mutter.gschema.xml.in:68 -msgid "" -"Determines whether the use of popup and highlight frame should be disabled " -"for window cycling." -msgstr "使用 Tab 键轮换窗口时,是否要禁用切换弹窗及其高亮边框窗口。" - -#: data/org.gnome.mutter.gschema.xml.in:76 msgid "Delay focus changes until the pointer stops moving" msgstr "将焦点改变推迟到光标停止移动之后" -#: data/org.gnome.mutter.gschema.xml.in:77 +#: data/org.gnome.mutter.gschema.xml.in:68 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 " @@ -360,42 +347,42 @@ "如果为 true,而聚焦模式为“sloppy”或“mouse”,那么进入某个窗口时焦点将不会立即" "改变,而是等到光标停止移动之后。" -#: data/org.gnome.mutter.gschema.xml.in:87 +#: data/org.gnome.mutter.gschema.xml.in:78 msgid "Draggable border width" msgstr "可拖拽的边界宽度" -#: data/org.gnome.mutter.gschema.xml.in:88 +#: data/org.gnome.mutter.gschema.xml.in:79 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." msgstr "" "可拖拽的边界总数。如果主题的可见边界不足,将添加不可见的边界来满足此值。" -#: data/org.gnome.mutter.gschema.xml.in:97 +#: data/org.gnome.mutter.gschema.xml.in:88 msgid "Auto maximize nearly monitor sized windows" msgstr "自动最大化接近显示器大小的窗口" -#: data/org.gnome.mutter.gschema.xml.in:98 +#: data/org.gnome.mutter.gschema.xml.in:89 msgid "" "If enabled, new windows that are initially the size of the monitor " "automatically get maximized." msgstr "如果启用,初始时为显示器大小的新窗口将自动最大化。" -#: data/org.gnome.mutter.gschema.xml.in:106 +#: data/org.gnome.mutter.gschema.xml.in:97 msgid "Place new windows in the center" msgstr "将窗口置于中央" -#: data/org.gnome.mutter.gschema.xml.in:107 +#: data/org.gnome.mutter.gschema.xml.in:98 msgid "" "When true, the new windows will always be put in the center of the active " "screen of the monitor." msgstr "为 true 时,新窗口将总是置于此显示器已激活屏幕的中央。" -#: data/org.gnome.mutter.gschema.xml.in:116 +#: data/org.gnome.mutter.gschema.xml.in:107 msgid "Enable experimental features" msgstr "开启实验性功能" -#: data/org.gnome.mutter.gschema.xml.in:117 +#: data/org.gnome.mutter.gschema.xml.in:108 msgid "" "To enable experimental features, add the feature keyword to the list. " "Whether the feature requires restarting the compositor depends on the given " @@ -421,19 +408,19 @@ "幕共享。使用 i915 驱动时默认启用,其它驱动默认禁用。需要重启。•“autoclose-" "xwayland”——所有关联的 X11 客户端退出时自动终止 Xwayland。需要重启。" -#: data/org.gnome.mutter.gschema.xml.in:150 +#: data/org.gnome.mutter.gschema.xml.in:141 msgid "Modifier to use to locate the pointer" msgstr "用来定位指针的修饰键" -#: data/org.gnome.mutter.gschema.xml.in:151 +#: data/org.gnome.mutter.gschema.xml.in:142 msgid "This key will initiate the “locate pointer” action." msgstr "此按键将启动“定位指针”操作。" -#: data/org.gnome.mutter.gschema.xml.in:158 +#: data/org.gnome.mutter.gschema.xml.in:149 msgid "Timeout for check-alive ping" msgstr "检测活动的 ping 超时" -#: data/org.gnome.mutter.gschema.xml.in:159 +#: data/org.gnome.mutter.gschema.xml.in:150 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." @@ -441,19 +428,11 @@ "为了不被检测为冻结,客户端必须响应 ping 请求的毫秒数。使用 0 将完全禁用活动检" "测。" -#: data/org.gnome.mutter.gschema.xml.in:183 -msgid "Select window from tab popup" -msgstr "从 Tab 轮换弹出界面选择窗口" - -#: data/org.gnome.mutter.gschema.xml.in:188 -msgid "Cancel tab popup" -msgstr "取消 Tab 轮换弹窗" - -#: data/org.gnome.mutter.gschema.xml.in:193 +#: data/org.gnome.mutter.gschema.xml.in:174 msgid "Switch monitor configurations" msgstr "切换显示器配置" -#: data/org.gnome.mutter.gschema.xml.in:198 +#: data/org.gnome.mutter.gschema.xml.in:179 msgid "Rotates the built-in monitor configuration" msgstr "旋转内置显示器配置" @@ -571,6 +550,29 @@ "扩展时才有意义。如果 Xwayland 在构建时没有启用指定的扩展,该选项不会产生效" "果。要使配置生效,需要重新启动 Xwayland。" +#: data/org.gnome.mutter.wayland.gschema.xml.in:130 +msgid "Allow X11 clients with a different endianness to connect to Xwayland" +msgstr "允许使用不同字节序的 X11 客户端连接到 Xwayland。" + +#: data/org.gnome.mutter.wayland.gschema.xml.in:131 +msgid "" +"Allow connections from clients with an endianness different to that of " +"Xwayland. The X server byte-swapping code is a huge attack surface, much of " +"that code in Xwayland is prone to security issues. The use-case of byte-" +"swapped clients is very niche, and disabled by default in Xwayland. Enable " +"this option to instruct Xwayland to accept connections from X11 clients with " +"a different endianness. This option has no effect if Xwayland does not " +"support the command line option +byteswappedclients/-byteswappedclients to " +"control that setting. Xwayland needs to be restarted for this setting to " +"take effect." +msgstr "" +"允许来自字节序与 Xwayland 不同的客户端的连接。X 服务器的字节交换代码是一个巨" +"大的攻击面,Xwayland 中的许多代码很容易出现安全问题。字节交换客户端的使用情况" +"是非常小众的,并且在 Xwayland 中默认是禁用的。启用该选项可以指示 Xwayland 接" +"受来自 X11 客户端的不同字节序的连接。如果Xwayland 不支持命令行选项 " +"+byteswappedclients/-bytewappedclients 来控制该设置,则该选项没有效果。" +"Xwayland 需要重新启动以使该设置生效。" + #: src/backends/meta-monitor.c:253 msgid "Built-in display" msgstr "内置显示器" @@ -598,14 +600,9 @@ msgid "%s %s" msgstr "%s %s" -#. Translators: this string will appear in Sysprof -#: src/backends/meta-profiler.c:79 -msgid "Compositor" -msgstr "合成器" - #. 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:400 +#: src/compositor/compositor.c:416 #, c-format msgid "" "Another compositing manager is already running on screen %i on display “%s”." @@ -615,74 +612,74 @@ msgid "Bell event" msgstr "响铃事件" -#: src/core/display.c:693 +#: src/core/display.c:703 msgid "Privacy Screen Enabled" msgstr "隐私屏幕已启用" -#: src/core/display.c:694 +#: src/core/display.c:704 msgid "Privacy Screen Disabled" msgstr "隐私屏幕已禁用" -#: src/core/meta-context-main.c:567 +#: src/core/meta-context-main.c:579 msgid "Replace the running window manager" msgstr "替换正在运行的窗口管理器" -#: src/core/meta-context-main.c:573 +#: src/core/meta-context-main.c:585 msgid "X Display to use" msgstr "要使用的 X 显示" -#: src/core/meta-context-main.c:579 +#: src/core/meta-context-main.c:591 msgid "Disable connection to session manager" msgstr "禁止连接到会话管理器" -#: src/core/meta-context-main.c:585 +#: src/core/meta-context-main.c:597 msgid "Specify session management ID" msgstr "指定会话管理 ID" -#: src/core/meta-context-main.c:591 +#: src/core/meta-context-main.c:603 msgid "Initialize session from savefile" msgstr "从保存文件中初始化会话" -#: src/core/meta-context-main.c:597 +#: src/core/meta-context-main.c:609 msgid "Make X calls synchronous" msgstr "使 X 调用同步" -#: src/core/meta-context-main.c:605 +#: src/core/meta-context-main.c:617 msgid "Run as a wayland compositor" msgstr "以 wayland 合成器运行" -#: src/core/meta-context-main.c:611 +#: src/core/meta-context-main.c:623 msgid "Run as a nested compositor" msgstr "以嵌套合成器运行" -#: src/core/meta-context-main.c:617 +#: src/core/meta-context-main.c:629 msgid "Run wayland compositor without starting Xwayland" msgstr "运行 wayland 合成器但不启动 Xwayland" -#: src/core/meta-context-main.c:623 +#: src/core/meta-context-main.c:635 msgid "Specify Wayland display name to use" msgstr "指定要使用的 Wayland 显示的名称" -#: src/core/meta-context-main.c:631 +#: src/core/meta-context-main.c:643 msgid "Run as a full display server, rather than nested" msgstr "以完整显示服务器方式运行,而不是以嵌套方式" -#: src/core/meta-context-main.c:636 +#: src/core/meta-context-main.c:648 msgid "Run as a headless display server" msgstr "以无外设显示服务器运行" -#: src/core/meta-context-main.c:641 +#: src/core/meta-context-main.c:653 msgid "Add persistent virtual monitor (WxH or WxH@R)" msgstr "添加持久性虚拟显示器(WxH 或 WxH@R)" -#: src/core/meta-context-main.c:653 +#: src/core/meta-context-main.c:665 msgid "Run with X11 backend" msgstr "以 X11 后端运行" #. TRANSLATORS: This string refers to a button that switches between #. * different modes. #. -#: src/core/meta-pad-action-mapper.c:848 +#: src/core/meta-pad-action-mapper.c:861 #, c-format msgid "Mode Switch (Group %d)" msgstr "模式切换(组别 %d)" @@ -690,14 +687,19 @@ #. TRANSLATORS: This string refers to an action, cycles drawing tablets' #. * mapping through the available outputs. #. -#: src/core/meta-pad-action-mapper.c:871 +#: src/core/meta-pad-action-mapper.c:884 msgid "Switch monitor" msgstr "切换显示器" -#: src/core/meta-pad-action-mapper.c:873 +#: src/core/meta-pad-action-mapper.c:886 msgid "Show on-screen help" msgstr "显示在屏帮助" +#. Translators: this string will appear in Sysprof +#: src/core/meta-profiler.c:80 src/core/meta-profiler.c:217 +msgid "Compositor" +msgstr "合成器" + #: src/core/mutter.c:74 msgid "Print version" msgstr "打印版本" @@ -711,20 +713,20 @@ msgid "Workspace %d" msgstr "工作区 %d" -#: src/core/util.c:143 +#: src/core/util.c:142 msgid "Mutter was compiled without support for verbose mode" msgstr "Mutter 编译的时候没有加入详细模式的支持" -#: src/core/workspace.c:533 +#: src/core/workspace.c:541 msgid "Workspace switched" msgstr "工作区已切换" -#: src/wayland/meta-wayland-tablet-pad.c:520 +#: src/wayland/meta-wayland-tablet-pad.c:530 #, c-format msgid "Mode Switch: Mode %d" msgstr "模式切换:%d 模式" -#: src/x11/meta-x11-display.c:659 +#: src/x11/meta-x11-display.c:701 #, c-format msgid "" "Display “%s” already has a window manager; try using the --replace option to " @@ -732,30 +734,46 @@ msgstr "" "显示“%s”已经有一个窗口管理器;请尝试使用 --replace 选项替换当前的窗口管理器。" -#: src/x11/meta-x11-display.c:1053 -msgid "Failed to initialize GDK" -msgstr "初始化 GDK 失败" - -#: src/x11/meta-x11-display.c:1080 +#: src/x11/meta-x11-display.c:1062 #, c-format msgid "Failed to open X Window System display “%s”" msgstr "无法打开 X 窗口系统显示“%s”" -#: src/x11/meta-x11-display.c:1188 +#: src/x11/meta-x11-display.c:1207 #, c-format msgid "Screen %d on display “%s” is invalid" msgstr "显示“%2$s”上的屏幕 %1$d 无效" -#: src/x11/meta-x11-selection-input-stream.c:474 +#: src/x11/meta-x11-selection-input-stream.c:481 #, c-format msgid "Format %s not supported" msgstr "不支持 %s 格式" -#: src/x11/window-props.c:548 +#: src/x11/window-props.c:549 #, c-format msgid "%s (on %s)" msgstr "%s(于 %s)" +#~ msgid "Mutter" +#~ msgstr "Mutter" + +#~ msgid "No tab popup" +#~ msgstr "无 Tab 轮换弹窗" + +#~ msgid "" +#~ "Determines whether the use of popup and highlight frame should be " +#~ "disabled for window cycling." +#~ msgstr "使用 Tab 键轮换窗口时,是否要禁用切换弹窗及其高亮边框窗口。" + +#~ msgid "Select window from tab popup" +#~ msgstr "从 Tab 轮换弹出界面选择窗口" + +#~ msgid "Cancel tab popup" +#~ msgstr "取消 Tab 轮换弹窗" + +#~ msgid "Failed to initialize GDK" +#~ msgstr "初始化 GDK 失败" + #, c-format #~ msgid "“%s” is not responding." #~ msgstr "“%s” 未响应。" diff -Nru mutter-44.0/src/backends/meta-backend.c mutter-44.1/src/backends/meta-backend.c --- mutter-44.0/src/backends/meta-backend.c 2023-03-19 10:55:05.000000000 +0000 +++ mutter-44.1/src/backends/meta-backend.c 2023-04-25 16:16:17.000000000 +0000 @@ -63,6 +63,7 @@ #include "backends/meta-input-settings-private.h" #include "backends/meta-logical-monitor.h" #include "backends/meta-monitor-manager-dummy.h" +#include "backends/meta-remote-access-controller-private.h" #include "backends/meta-settings-private.h" #include "backends/meta-stage-private.h" #include "backends/x11/meta-backend-x11.h" @@ -77,7 +78,6 @@ #include "meta/util.h" #ifdef HAVE_REMOTE_DESKTOP -#include "backends/meta-remote-access-controller-private.h" #include "backends/meta-remote-desktop.h" #include "backends/meta-screen-cast.h" #endif @@ -134,8 +134,8 @@ #endif MetaSettings *settings; MetaDbusSessionWatcher *dbus_session_watcher; -#ifdef HAVE_REMOTE_DESKTOP MetaRemoteAccessController *remote_access_controller; +#ifdef HAVE_REMOTE_DESKTOP MetaScreenCast *screen_cast; MetaRemoteDesktop *remote_desktop; #endif @@ -1410,13 +1410,9 @@ MetaRemoteAccessController * meta_backend_get_remote_access_controller (MetaBackend *backend) { -#ifdef HAVE_REMOTE_DESKTOP MetaBackendPrivate *priv = meta_backend_get_instance_private (backend); return priv->remote_access_controller; -#else - return NULL; -#endif } /** diff -Nru mutter-44.0/src/backends/meta-backend-private.h mutter-44.1/src/backends/meta-backend-private.h --- mutter-44.0/src/backends/meta-backend-private.h 2023-03-19 10:55:05.000000000 +0000 +++ mutter-44.1/src/backends/meta-backend-private.h 2023-04-25 16:16:17.000000000 +0000 @@ -135,6 +135,7 @@ MetaCursorTracker * meta_backend_get_cursor_tracker (MetaBackend *backend); MetaCursorRenderer * meta_backend_get_cursor_renderer_for_device (MetaBackend *backend, ClutterInputDevice *device); +META_EXPORT_TEST MetaCursorRenderer * meta_backend_get_cursor_renderer (MetaBackend *backend); META_EXPORT_TEST MetaRenderer * meta_backend_get_renderer (MetaBackend *backend); diff -Nru mutter-44.0/src/backends/meta-crtc.c mutter-44.1/src/backends/meta-crtc.c --- mutter-44.0/src/backends/meta-crtc.c 2023-03-19 10:55:05.000000000 +0000 +++ mutter-44.1/src/backends/meta-crtc.c 2023-04-25 16:16:17.000000000 +0000 @@ -229,11 +229,7 @@ if (gamma->size == target_size) return meta_gamma_lut_copy (gamma); - out = meta_gamma_lut_new (target_size, NULL, NULL, NULL); - - out->red = g_new0 (uint16_t, target_size); - out->green = g_new0 (uint16_t, target_size); - out->blue = g_new0 (uint16_t, target_size); + out = meta_gamma_lut_new_sized (target_size); if (target_size >= gamma->size) { diff -Nru mutter-44.0/src/backends/meta-cursor-renderer.h mutter-44.1/src/backends/meta-cursor-renderer.h --- mutter-44.0/src/backends/meta-cursor-renderer.h 2023-03-19 10:55:05.000000000 +0000 +++ mutter-44.1/src/backends/meta-cursor-renderer.h 2023-04-25 16:16:17.000000000 +0000 @@ -29,6 +29,7 @@ #include "backends/meta-backend-types.h" #include "backends/meta-cursor.h" +#include "core/util-private.h" #define META_TYPE_HW_CURSOR_INHIBITOR (meta_hw_cursor_inhibitor_get_type ()) G_DECLARE_INTERFACE (MetaHwCursorInhibitor, meta_hw_cursor_inhibitor, @@ -64,6 +65,7 @@ void meta_cursor_renderer_update_position (MetaCursorRenderer *renderer); void meta_cursor_renderer_force_update (MetaCursorRenderer *renderer); +META_EXPORT_TEST MetaCursorSprite * meta_cursor_renderer_get_cursor (MetaCursorRenderer *renderer); graphene_rect_t meta_cursor_renderer_calculate_rect (MetaCursorRenderer *renderer, diff -Nru mutter-44.0/src/backends/meta-cursor-tracker.c mutter-44.1/src/backends/meta-cursor-tracker.c --- mutter-44.0/src/backends/meta-cursor-tracker.c 2023-03-19 10:55:05.000000000 +0000 +++ mutter-44.1/src/backends/meta-cursor-tracker.c 2023-04-25 16:16:17.000000000 +0000 @@ -263,6 +263,7 @@ g_clear_object (&priv->effective_cursor); g_clear_object (&priv->displayed_cursor); + g_clear_object (&priv->window_cursor); g_clear_object (&priv->root_cursor); G_OBJECT_CLASS (meta_cursor_tracker_parent_class)->dispose (object); @@ -319,7 +320,7 @@ * * Retrieves the cursor tracker object for @display. * - * Returns: (transfer none): + * Returns: (transfer none): the cursor tracker object for @display. */ MetaCursorTracker * meta_cursor_tracker_get_for_display (MetaDisplay *display) @@ -350,8 +351,11 @@ /** * meta_cursor_tracker_get_sprite: + * @tracker: a #MetaCursorTracker + * + * Get the #CoglTexture of the cursor sprite * - * Returns: (transfer none): + * Returns: (transfer none) (nullable): the #CoglTexture of the cursor sprite */ CoglTexture * meta_cursor_tracker_get_sprite (MetaCursorTracker *tracker) @@ -369,9 +373,11 @@ /** * meta_cursor_tracker_get_scale: - * @tracker: + * @tracker: a #MetaCursorTracker + * + * Get the scale factor of the cursor sprite * - * Returns: + * Returns: The scale factor of the cursor sprite */ float meta_cursor_tracker_get_scale (MetaCursorTracker *tracker) @@ -388,10 +394,11 @@ /** * meta_cursor_tracker_get_hot: - * @tracker: - * @x: (out): - * @y: (out): + * @tracker: a #MetaCursorTracker + * @x: (out): the x coordinate of the cursor hotspot + * @y: (out): the y coordinate of the cursor hotspot * + * Get the hotspot of the current cursor sprite. */ void meta_cursor_tracker_get_hot (MetaCursorTracker *tracker, @@ -431,7 +438,7 @@ /** * meta_cursor_tracker_set_root_cursor: * @tracker: a #MetaCursorTracker object. - * @cursor_sprite: (transfer none): the new root cursor + * @cursor_sprite: (transfer none) (nullable): the new root cursor * * Sets the root cursor (the cursor that is shown if not modified by a window). * The #MetaCursorTracker will take a strong reference to the sprite. @@ -459,8 +466,8 @@ /** * meta_cursor_tracker_get_pointer: * @tracker: a #MetaCursorTracker object - * @coords: (out caller-allocates): the coordinates of the pointer - * @mods: (out): the current #ClutterModifierType of the pointer + * @coords: (out caller-allocates) (optional): the coordinates of the pointer + * @mods: (out) (optional): the current #ClutterModifierType of the pointer * * Get the current pointer position and state. */ diff -Nru mutter-44.0/src/backends/meta-monitor.c mutter-44.1/src/backends/meta-monitor.c --- mutter-44.0/src/backends/meta-monitor.c 2023-03-19 10:55:05.000000000 +0000 +++ mutter-44.1/src/backends/meta-monitor.c 2023-04-25 16:16:17.000000000 +0000 @@ -613,14 +613,17 @@ generate_mode_id (MetaMonitorModeSpec *monitor_mode_spec) { gboolean is_interlaced; + char rate_str[G_ASCII_DTOSTR_BUF_SIZE]; is_interlaced = !!(monitor_mode_spec->flags & META_CRTC_MODE_FLAG_INTERLACE); + g_ascii_formatd (rate_str, sizeof (rate_str), + "%.3f", monitor_mode_spec->refresh_rate); - return g_strdup_printf ("%dx%d%s@%.3f", + return g_strdup_printf ("%dx%d%s@%s", monitor_mode_spec->width, monitor_mode_spec->height, is_interlaced ? "i" : "", - monitor_mode_spec->refresh_rate); + rate_str); } static gboolean @@ -2302,3 +2305,50 @@ return TRUE; } + +gboolean +meta_parse_monitor_mode (const char *string, + int *out_width, + int *out_height, + float *out_refresh_rate, + float fallback_refresh_rate) +{ + char *ptr = (char *) string; + int width, height; + float refresh_rate; + + width = g_ascii_strtoull (ptr, &ptr, 10); + if (width == 0) + return FALSE; + + if (ptr[0] != 'x') + return FALSE; + ptr++; + + height = g_ascii_strtoull (ptr, &ptr, 10); + if (height == 0) + return FALSE; + + if (ptr[0] == '\0') + { + refresh_rate = fallback_refresh_rate; + goto out; + } + + if (ptr[0] != '@') + return FALSE; + ptr++; + + refresh_rate = g_ascii_strtod (ptr, &ptr); + if (refresh_rate == 0.0) + return FALSE; + + if (ptr[0] != '\0') + return FALSE; + +out: + *out_width = width; + *out_height = height; + *out_refresh_rate = refresh_rate; + return TRUE; +} diff -Nru mutter-44.0/src/backends/meta-monitor.h mutter-44.1/src/backends/meta-monitor.h --- mutter-44.0/src/backends/meta-monitor.h 2023-03-19 10:55:05.000000000 +0000 +++ mutter-44.1/src/backends/meta-monitor.h 2023-04-25 16:16:17.000000000 +0000 @@ -318,4 +318,11 @@ MetaOutputHdrMetadata *metadata, GError **error); +META_EXPORT_TEST +gboolean meta_parse_monitor_mode (const char *string, + int *out_width, + int *out_height, + float *out_refresh_rate, + float fallback_refresh_rate); + #endif /* META_MONITOR_H */ diff -Nru mutter-44.0/src/backends/meta-monitor-manager.c mutter-44.1/src/backends/meta-monitor-manager.c --- mutter-44.0/src/backends/meta-monitor-manager.c 2023-03-19 10:55:05.000000000 +0000 +++ mutter-44.1/src/backends/meta-monitor-manager.c 2023-04-25 16:16:17.000000000 +0000 @@ -520,7 +520,7 @@ meta_monitor_get_display_name (monitor), error->message); meta_monitor_set_color_space (monitor, - META_OUTPUT_COLORSPACE_UNKNOWN, + META_OUTPUT_COLORSPACE_DEFAULT, NULL); continue; @@ -535,7 +535,7 @@ meta_monitor_get_display_name (monitor), error->message); meta_monitor_set_color_space (monitor, - META_OUTPUT_COLORSPACE_UNKNOWN, + META_OUTPUT_COLORSPACE_DEFAULT, NULL); meta_monitor_set_hdr_metadata (monitor, &(MetaOutputHdrMetadata) { .active = FALSE, diff -Nru mutter-44.0/src/backends/meta-monitor-manager-dummy.c mutter-44.1/src/backends/meta-monitor-manager-dummy.c --- mutter-44.0/src/backends/meta-monitor-manager-dummy.c 2023-03-19 10:55:05.000000000 +0000 +++ mutter-44.1/src/backends/meta-monitor-manager-dummy.c 2023-04-25 16:16:17.000000000 +0000 @@ -159,12 +159,10 @@ for (i = 0; specs[i]; ++i) { int width, height; - float refresh_rate = 60.0; + float refresh_rate; - if (sscanf (specs[i], "%dx%d@%f", - &width, &height, &refresh_rate) == 3 || - sscanf (specs[i], "%dx%d", - &width, &height) == 2) + if (meta_parse_monitor_mode (specs[i], &width, &height, &refresh_rate, + 60.0)) { CrtcModeSpec *spec; diff -Nru mutter-44.0/src/backends/meta-output.c mutter-44.1/src/backends/meta-output.c --- mutter-44.0/src/backends/meta-output.c 2023-03-19 10:55:05.000000000 +0000 +++ mutter-44.1/src/backends/meta-output.c 2023-04-25 16:16:17.000000000 +0000 @@ -529,16 +529,37 @@ } gboolean +meta_output_info_is_color_space_supported (const MetaOutputInfo *output_info, + MetaOutputColorspace color_space) +{ + MetaEdidColorimetry colorimetry; + + if (!output_info->edid_info) + return FALSE; + + colorimetry = output_info->edid_info->colorimetry; + + switch (color_space) + { + case META_OUTPUT_COLORSPACE_DEFAULT: + return TRUE; + case META_OUTPUT_COLORSPACE_BT2020: + return !!(colorimetry & META_EDID_COLORIMETRY_BT2020RGB); + default: + return FALSE; + } +} + +gboolean meta_output_is_color_space_supported (MetaOutput *output, MetaOutputColorspace color_space) { MetaOutputClass *output_class = META_OUTPUT_GET_CLASS (output); - uint64_t supported = 0; - if (output_class->get_supported_color_spaces) - supported = output_class->get_supported_color_spaces (output); + if (!output_class->is_color_space_supported) + return FALSE; - return supported & (1 << color_space); + return output_class->is_color_space_supported (output, color_space); } void @@ -626,7 +647,7 @@ MetaOutputPrivate *priv = meta_output_get_instance_private (output); priv->backlight = -1; - priv->color_space = META_OUTPUT_COLORSPACE_UNKNOWN; + priv->color_space = META_OUTPUT_COLORSPACE_DEFAULT; priv->hdr_metadata.active = FALSE; } diff -Nru mutter-44.0/src/backends/meta-output.h mutter-44.1/src/backends/meta-output.h --- mutter-44.0/src/backends/meta-output.h 2023-03-19 10:55:05.000000000 +0000 +++ mutter-44.1/src/backends/meta-output.h 2023-04-25 16:16:17.000000000 +0000 @@ -182,6 +182,9 @@ void meta_output_info_parse_edid (MetaOutputInfo *output_info, GBytes *edid); +gboolean meta_output_info_is_color_space_supported (const MetaOutputInfo *output_info, + MetaOutputColorspace color_space); + gboolean meta_output_is_laptop (MetaOutput *output); G_DEFINE_AUTOPTR_CLEANUP_FUNC (MetaOutputInfo, meta_output_info_unref) @@ -198,7 +201,8 @@ gboolean (* set_privacy_screen_enabled) (MetaOutput *output, gboolean enabled, GError **error); - uint64_t (* get_supported_color_spaces) (MetaOutput *output); + gboolean (* is_color_space_supported) (MetaOutput *output, + MetaOutputColorspace color_space); gboolean (* is_hdr_metadata_supported) (MetaOutput *output); }; diff -Nru mutter-44.0/src/backends/meta-screen-cast-area-stream-src.c mutter-44.1/src/backends/meta-screen-cast-area-stream-src.c --- mutter-44.0/src/backends/meta-screen-cast-area-stream-src.c 2023-03-19 10:55:05.000000000 +0000 +++ mutter-44.1/src/backends/meta-screen-cast-area-stream-src.c 2023-04-25 16:16:17.000000000 +0000 @@ -169,7 +169,7 @@ return; flags = META_SCREEN_CAST_RECORD_FLAG_CURSOR_ONLY; - meta_screen_cast_stream_src_maybe_record_frame (src, flags); + meta_screen_cast_stream_src_maybe_record_frame (src, flags, NULL); } static void @@ -239,7 +239,7 @@ area_src->maybe_record_idle_id = 0; flags = META_SCREEN_CAST_RECORD_FLAG_NONE; - meta_screen_cast_stream_src_maybe_record_frame (src, flags); + meta_screen_cast_stream_src_maybe_record_frame (src, flags, NULL); return G_SOURCE_REMOVE; } @@ -248,6 +248,7 @@ before_stage_painted (MetaStage *stage, ClutterStageView *view, ClutterPaintContext *paint_context, + ClutterFrame *frame, gpointer user_data) { MetaScreenCastAreaStreamSrc *area_src = @@ -267,6 +268,7 @@ stage_painted (MetaStage *stage, ClutterStageView *view, ClutterPaintContext *paint_context, + ClutterFrame *frame, gpointer user_data) { MetaScreenCastAreaStreamSrc *area_src = @@ -544,7 +546,7 @@ g_clear_handle_id (&area_src->maybe_record_idle_id, g_source_remove); flags = META_SCREEN_CAST_RECORD_FLAG_NONE; - meta_screen_cast_stream_src_maybe_record_frame (src, flags); + meta_screen_cast_stream_src_maybe_record_frame (src, flags, NULL); } static void diff -Nru mutter-44.0/src/backends/meta-screen-cast-monitor-stream-src.c mutter-44.1/src/backends/meta-screen-cast-monitor-stream-src.c --- mutter-44.0/src/backends/meta-screen-cast-monitor-stream-src.c 2023-03-19 10:55:05.000000000 +0000 +++ mutter-44.1/src/backends/meta-screen-cast-monitor-stream-src.c 2023-04-25 16:16:17.000000000 +0000 @@ -143,7 +143,7 @@ monitor_src->maybe_record_idle_id = 0; flags = META_SCREEN_CAST_RECORD_FLAG_NONE; - meta_screen_cast_stream_src_maybe_record_frame (src, flags); + meta_screen_cast_stream_src_maybe_record_frame (src, flags, NULL); return G_SOURCE_REMOVE; } @@ -152,31 +152,50 @@ stage_painted (MetaStage *stage, ClutterStageView *view, ClutterPaintContext *paint_context, + ClutterFrame *frame, gpointer user_data) { MetaScreenCastMonitorStreamSrc *monitor_src = META_SCREEN_CAST_MONITOR_STREAM_SRC (user_data); MetaScreenCastStreamSrc *src = META_SCREEN_CAST_STREAM_SRC (monitor_src); + MetaScreenCastRecordResult record_result; + MetaScreenCastRecordFlag flags; + int64_t presentation_time_us; if (monitor_src->maybe_record_idle_id) return; - monitor_src->maybe_record_idle_id = g_idle_add (maybe_record_frame_on_idle, - src); - g_source_set_name_by_id (monitor_src->maybe_record_idle_id, - "[mutter] maybe_record_frame_on_idle [monitor-src]"); + if (!clutter_frame_get_target_presentation_time (frame, &presentation_time_us)) + presentation_time_us = g_get_monotonic_time (); + + flags = META_SCREEN_CAST_RECORD_FLAG_DMABUF_ONLY; + record_result = + meta_screen_cast_stream_src_maybe_record_frame_with_timestamp (src, + flags, + NULL, + presentation_time_us); + + if (!(record_result & META_SCREEN_CAST_RECORD_RESULT_RECORDED_FRAME)) + { + monitor_src->maybe_record_idle_id = g_idle_add (maybe_record_frame_on_idle, + src); + g_source_set_name_by_id (monitor_src->maybe_record_idle_id, + "[mutter] maybe_record_frame_on_idle [monitor-src]"); + } } static void before_stage_painted (MetaStage *stage, ClutterStageView *view, ClutterPaintContext *paint_context, + ClutterFrame *frame, gpointer user_data) { MetaScreenCastMonitorStreamSrc *monitor_src = META_SCREEN_CAST_MONITOR_STREAM_SRC (user_data); MetaScreenCastStreamSrc *src = META_SCREEN_CAST_STREAM_SRC (monitor_src); MetaScreenCastRecordFlag flags; + int64_t presentation_time_us; if (monitor_src->maybe_record_idle_id) return; @@ -184,8 +203,14 @@ if (!clutter_stage_view_peek_scanout (view)) return; + if (!clutter_frame_get_target_presentation_time (frame, &presentation_time_us)) + presentation_time_us = g_get_monotonic_time (); + flags = META_SCREEN_CAST_RECORD_FLAG_DMABUF_ONLY; - meta_screen_cast_stream_src_maybe_record_frame (src, flags); + meta_screen_cast_stream_src_maybe_record_frame_with_timestamp (src, + flags, + NULL, + presentation_time_us); } static gboolean @@ -264,7 +289,7 @@ return; flags = META_SCREEN_CAST_RECORD_FLAG_CURSOR_ONLY; - meta_screen_cast_stream_src_maybe_record_frame (src, flags); + meta_screen_cast_stream_src_maybe_record_frame (src, flags, NULL); } static void diff -Nru mutter-44.0/src/backends/meta-screen-cast-stream-src.c mutter-44.1/src/backends/meta-screen-cast-stream-src.c --- mutter-44.0/src/backends/meta-screen-cast-stream-src.c 2023-03-19 10:55:05.000000000 +0000 +++ mutter-44.1/src/backends/meta-screen-cast-stream-src.c 2023-04-25 16:16:17.000000000 +0000 @@ -51,6 +51,7 @@ (sizeof (struct spa_meta_cursor) + \ sizeof (struct spa_meta_bitmap) + width * height * 4) +#define NUM_DAMAGED_RECTS 32 #define DEFAULT_SIZE SPA_RECTANGLE (1280, 720) #define MIN_SIZE SPA_RECTANGLE (1, 1) #define MAX_SIZE SPA_RECTANGLE (16384, 16386) @@ -107,6 +108,8 @@ guint follow_up_frame_source_id; GHashTable *dmabuf_handles; + + cairo_region_t *redraw_clip; } MetaScreenCastStreamSrcPrivate; static struct spa_pod * @@ -481,7 +484,7 @@ meta_screen_cast_stream_src_set_cursor_metadata (src, spa_meta_cursor); } -static void +static MetaScreenCastRecordResult maybe_record_cursor (MetaScreenCastStreamSrc *src, struct spa_buffer *spa_buffer) { @@ -490,11 +493,12 @@ switch (meta_screen_cast_stream_get_cursor_mode (stream)) { case META_SCREEN_CAST_CURSOR_MODE_HIDDEN: + return META_SCREEN_CAST_RECORD_RESULT_RECORDED_NOTHING; case META_SCREEN_CAST_CURSOR_MODE_EMBEDDED: - return; + return META_SCREEN_CAST_RECORD_RESULT_RECORDED_CURSOR; case META_SCREEN_CAST_CURSOR_MODE_METADATA: add_cursor_metadata (src, spa_buffer); - return; + return META_SCREEN_CAST_RECORD_RESULT_RECORDED_CURSOR; } g_assert_not_reached (); @@ -512,6 +516,9 @@ gboolean dmabuf_only; dmabuf_only = flags & META_SCREEN_CAST_RECORD_FLAG_DMABUF_ONLY; + if (dmabuf_only && spa_buffer->datas[0].type != SPA_DATA_DmaBuf) + return FALSE; + if (!dmabuf_only && (spa_buffer->datas[0].data || spa_buffer->datas[0].type == SPA_DATA_MemFd)) @@ -602,21 +609,116 @@ return priv->video_stride; } -void +static void +maybe_add_damaged_regions_metadata (MetaScreenCastStreamSrc *src, + struct spa_buffer *spa_buffer) +{ + MetaScreenCastStreamSrcPrivate *priv; + struct spa_meta *spa_meta_video_damage; + struct spa_meta_region *meta_region; + + spa_meta_video_damage = + spa_buffer_find_meta (spa_buffer, SPA_META_VideoDamage); + if (!spa_meta_video_damage) + return; + + priv = meta_screen_cast_stream_src_get_instance_private (src); + if (!priv->redraw_clip) + { + spa_meta_for_each (meta_region, spa_meta_video_damage) + { + meta_region->region = SPA_REGION (0, 0, priv->video_format.size.width, + priv->video_format.size.height); + break; + } + } + else + { + int i; + int n_rectangles; + int num_buffers_available; + + i = 0; + n_rectangles = cairo_region_num_rectangles (priv->redraw_clip); + num_buffers_available = 0; + + spa_meta_for_each (meta_region, spa_meta_video_damage) + { + ++num_buffers_available; + } + + if (num_buffers_available < n_rectangles) + { + spa_meta_for_each (meta_region, spa_meta_video_damage) + { + g_warning ("Not enough buffers (%d) to accomodate damaged " + "regions (%d)", num_buffers_available, n_rectangles); + meta_region->region = SPA_REGION (0, 0, + priv->video_format.size.width, + priv->video_format.size.height); + + break; + } + } + else + { + spa_meta_for_each (meta_region, spa_meta_video_damage) + { + cairo_rectangle_int_t rect; + + cairo_region_get_rectangle (priv->redraw_clip, i, &rect); + meta_region->region = SPA_REGION (rect.x, rect.y, + rect.width, rect.height); + + if (++i == n_rectangles) + break; + } + } + } + + g_clear_pointer (&priv->redraw_clip, cairo_region_destroy); +} + +MetaScreenCastRecordResult meta_screen_cast_stream_src_maybe_record_frame (MetaScreenCastStreamSrc *src, - MetaScreenCastRecordFlag flags) + MetaScreenCastRecordFlag flags, + const cairo_region_t *redraw_clip) +{ + int64_t now_us = g_get_monotonic_time (); + + return meta_screen_cast_stream_src_maybe_record_frame_with_timestamp (src, + flags, + redraw_clip, + now_us); +} + +MetaScreenCastRecordResult +meta_screen_cast_stream_src_maybe_record_frame_with_timestamp (MetaScreenCastStreamSrc *src, + MetaScreenCastRecordFlag flags, + const cairo_region_t *redraw_clip, + int64_t frame_timestamp_us) { MetaScreenCastStreamSrcPrivate *priv = meta_screen_cast_stream_src_get_instance_private (src); + MetaScreenCastRecordResult record_result = + META_SCREEN_CAST_RECORD_RESULT_RECORDED_NOTHING; MetaRectangle crop_rect; struct pw_buffer *buffer; struct spa_buffer *spa_buffer; struct spa_meta_header *header; uint8_t *data = NULL; - uint64_t now_us; - g_autoptr (GError) error = NULL; - now_us = g_get_monotonic_time (); + /* Accumulate the damaged region since we might not schedule a frame capture + * eventually but once we do, we should report all the previous damaged areas. + */ + if (redraw_clip) + { + if (priv->redraw_clip) + cairo_region_union (priv->redraw_clip, redraw_clip); + else + priv->redraw_clip = cairo_region_copy (redraw_clip); + } + if (priv->video_format.max_framerate.num > 0 && priv->last_frame_timestamp_us != 0) { @@ -627,7 +729,7 @@ ((G_USEC_PER_SEC * ((int64_t) priv->video_format.max_framerate.denom)) / ((int64_t) priv->video_format.max_framerate.num)); - time_since_last_frame_us = now_us - priv->last_frame_timestamp_us; + time_since_last_frame_us = frame_timestamp_us - priv->last_frame_timestamp_us; if (time_since_last_frame_us < min_interval_us) { int64_t timeout_us; @@ -637,16 +739,16 @@ meta_topic (META_DEBUG_SCREEN_CAST, "Skipped recording frame on stream %u, too early", priv->node_id); - return; + return record_result; } } if (!priv->pipewire_stream) - return; + return META_SCREEN_CAST_RECORD_RESULT_RECORDED_NOTHING; meta_topic (META_DEBUG_SCREEN_CAST, "Recording %s frame on stream %u", flags & META_SCREEN_CAST_RECORD_FLAG_CURSOR_ONLY ? - "cursor" : "full", + "cursor" : "full", priv->node_id); buffer = pw_stream_dequeue_buffer (priv->pipewire_stream); @@ -656,7 +758,7 @@ "Couldn't dequeue a buffer from pipewire stream (node id %u), " "maybe your encoding is too slow?", pw_stream_get_node_id (priv->pipewire_stream)); - return; + return record_result; } spa_buffer = buffer->buffer; @@ -673,14 +775,17 @@ header->flags = SPA_META_HEADER_FLAG_CORRUPTED; pw_stream_queue_buffer (priv->pipewire_stream, buffer); - return; + return record_result; } if (!(flags & META_SCREEN_CAST_RECORD_FLAG_CURSOR_ONLY)) { + g_autoptr (GError) error = NULL; + g_clear_handle_id (&priv->follow_up_frame_source_id, g_source_remove); if (do_record_frame (src, flags, spa_buffer, data, &error)) { + maybe_add_damaged_regions_metadata (src, spa_buffer); struct spa_data *spa_data = &spa_buffer->datas[0]; struct spa_meta_region *spa_meta_video_crop; @@ -712,10 +817,13 @@ priv->video_format.size.height; } } + + record_result |= META_SCREEN_CAST_RECORD_RESULT_RECORDED_FRAME; } else { - g_warning ("Failed to record screen cast frame: %s", error->message); + if (error) + g_warning ("Failed to record screen cast frame: %s", error->message); spa_buffer->datas[0].chunk->size = 0; spa_buffer->datas[0].chunk->flags = SPA_CHUNK_FLAG_CORRUPTED; } @@ -726,17 +834,19 @@ spa_buffer->datas[0].chunk->flags = SPA_CHUNK_FLAG_CORRUPTED; } - maybe_record_cursor (src, spa_buffer); + record_result |= maybe_record_cursor (src, spa_buffer); - priv->last_frame_timestamp_us = now_us; + priv->last_frame_timestamp_us = frame_timestamp_us; if (header) { - header->pts = now_us * SPA_NSEC_PER_USEC; + header->pts = frame_timestamp_us * SPA_NSEC_PER_USEC; header->flags = 0; } pw_stream_queue_buffer (priv->pipewire_stream, buffer); + + return record_result; } gboolean @@ -824,6 +934,23 @@ } static void +add_video_damage_meta_param (struct spa_pod_builder *pod_builder, + const struct spa_pod **params, + int idx) +{ + const size_t meta_region_size = sizeof (struct spa_meta_region); + + params[idx] = spa_pod_builder_add_object ( + pod_builder, + SPA_TYPE_OBJECT_ParamMeta, SPA_PARAM_Meta, + SPA_PARAM_META_type, SPA_POD_Id (SPA_META_VideoDamage), + SPA_PARAM_META_size, + SPA_POD_CHOICE_RANGE_Int (meta_region_size * NUM_DAMAGED_RECTS, + meta_region_size * 1, + meta_region_size * NUM_DAMAGED_RECTS)); +} + +static void on_stream_param_changed (void *data, uint32_t id, const struct spa_pod *format) @@ -836,7 +963,8 @@ uint8_t params_buffer[1024]; int32_t width, height, stride, size; struct spa_pod_builder pod_builder; - const struct spa_pod *params[4]; + const struct spa_pod *params[5]; + int n_params = 0; const int bpp = 4; int buffer_types; @@ -859,7 +987,7 @@ if (spa_pod_find_prop (format, NULL, SPA_FORMAT_VIDEO_modifier)) buffer_types |= 1 << SPA_DATA_DmaBuf; - params[0] = spa_pod_builder_add_object ( + params[n_params++] = spa_pod_builder_add_object ( &pod_builder, SPA_TYPE_OBJECT_ParamBuffers, SPA_PARAM_Buffers, SPA_PARAM_BUFFERS_buffers, SPA_POD_CHOICE_RANGE_Int (16, 2, 16), @@ -869,25 +997,27 @@ SPA_PARAM_BUFFERS_align, SPA_POD_Int (16), SPA_PARAM_BUFFERS_dataType, SPA_POD_CHOICE_FLAGS_Int (buffer_types)); - params[1] = spa_pod_builder_add_object ( + params[n_params++] = spa_pod_builder_add_object ( &pod_builder, SPA_TYPE_OBJECT_ParamMeta, SPA_PARAM_Meta, SPA_PARAM_META_type, SPA_POD_Id (SPA_META_VideoCrop), SPA_PARAM_META_size, SPA_POD_Int (sizeof (struct spa_meta_region))); - params[2] = spa_pod_builder_add_object ( + params[n_params++] = spa_pod_builder_add_object ( &pod_builder, SPA_TYPE_OBJECT_ParamMeta, SPA_PARAM_Meta, SPA_PARAM_META_type, SPA_POD_Id (SPA_META_Cursor), SPA_PARAM_META_size, SPA_POD_Int (CURSOR_META_SIZE (384, 384))); - params[3] = spa_pod_builder_add_object ( + params[n_params++] = spa_pod_builder_add_object ( &pod_builder, SPA_TYPE_OBJECT_ParamMeta, SPA_PARAM_Meta, SPA_PARAM_META_type, SPA_POD_Id (SPA_META_Header), SPA_PARAM_META_size, SPA_POD_Int (sizeof (struct spa_meta_header))); - pw_stream_update_params (priv->pipewire_stream, params, G_N_ELEMENTS (params)); + add_video_damage_meta_param (&pod_builder, params, n_params++); + + pw_stream_update_params (priv->pipewire_stream, params, n_params); if (klass->notify_params_updated) klass->notify_params_updated (src, &priv->video_format); diff -Nru mutter-44.0/src/backends/meta-screen-cast-stream-src.h mutter-44.1/src/backends/meta-screen-cast-stream-src.h --- mutter-44.0/src/backends/meta-screen-cast-stream-src.h 2023-03-19 10:55:05.000000000 +0000 +++ mutter-44.1/src/backends/meta-screen-cast-stream-src.h 2023-04-25 16:16:17.000000000 +0000 @@ -44,6 +44,13 @@ META_SCREEN_CAST_RECORD_FLAG_DMABUF_ONLY = 1 << 1, } MetaScreenCastRecordFlag; +typedef enum _MetaScreenCastRecordResult +{ + META_SCREEN_CAST_RECORD_RESULT_RECORDED_NOTHING = 0, + META_SCREEN_CAST_RECORD_RESULT_RECORDED_FRAME = 1 << 0, + META_SCREEN_CAST_RECORD_RESULT_RECORDED_CURSOR = 1 << 1, +} MetaScreenCastRecordResult; + #define META_TYPE_SCREEN_CAST_STREAM_SRC (meta_screen_cast_stream_src_get_type ()) G_DECLARE_DERIVABLE_TYPE (MetaScreenCastStreamSrc, meta_screen_cast_stream_src, @@ -84,8 +91,14 @@ gboolean meta_screen_cast_stream_src_is_enabled (MetaScreenCastStreamSrc *src); -void meta_screen_cast_stream_src_maybe_record_frame (MetaScreenCastStreamSrc *src, - MetaScreenCastRecordFlag flags); +MetaScreenCastRecordResult meta_screen_cast_stream_src_maybe_record_frame (MetaScreenCastStreamSrc *src, + MetaScreenCastRecordFlag flags, + const cairo_region_t *redraw_clip); + +MetaScreenCastRecordResult meta_screen_cast_stream_src_maybe_record_frame_with_timestamp (MetaScreenCastStreamSrc *src, + MetaScreenCastRecordFlag flags, + const cairo_region_t *redraw_clip, + int64_t frame_timestamp_us); gboolean meta_screen_cast_stream_src_pending_follow_up_frame (MetaScreenCastStreamSrc *src); diff -Nru mutter-44.0/src/backends/meta-screen-cast-virtual-stream-src.c mutter-44.1/src/backends/meta-screen-cast-virtual-stream-src.c --- mutter-44.0/src/backends/meta-screen-cast-virtual-stream-src.c 2023-03-19 10:55:05.000000000 +0000 +++ mutter-44.1/src/backends/meta-screen-cast-virtual-stream-src.c 2023-04-25 16:16:17.000000000 +0000 @@ -123,7 +123,7 @@ return; flags = META_SCREEN_CAST_RECORD_FLAG_CURSOR_ONLY; - meta_screen_cast_stream_src_maybe_record_frame (src, flags); + meta_screen_cast_stream_src_maybe_record_frame (src, flags, NULL); } static void @@ -186,13 +186,16 @@ actors_painted (MetaStage *stage, ClutterStageView *view, ClutterPaintContext *paint_context, + ClutterFrame *frame, gpointer user_data) { MetaScreenCastStreamSrc *src = META_SCREEN_CAST_STREAM_SRC (user_data); MetaScreenCastRecordFlag flags; + const cairo_region_t *redraw_clip = NULL; flags = META_SCREEN_CAST_RECORD_FLAG_NONE; - meta_screen_cast_stream_src_maybe_record_frame (src, flags); + redraw_clip = clutter_paint_context_get_redraw_clip (paint_context); + meta_screen_cast_stream_src_maybe_record_frame (src, flags, redraw_clip); } static void diff -Nru mutter-44.0/src/backends/meta-screen-cast-window-stream-src.c mutter-44.1/src/backends/meta-screen-cast-window-stream-src.c --- mutter-44.0/src/backends/meta-screen-cast-window-stream-src.c 2023-03-19 10:55:05.000000000 +0000 +++ mutter-44.1/src/backends/meta-screen-cast-window-stream-src.c 2023-04-25 16:16:17.000000000 +0000 @@ -373,7 +373,7 @@ MetaScreenCastRecordFlag flags; flags = META_SCREEN_CAST_RECORD_FLAG_NONE; - meta_screen_cast_stream_src_maybe_record_frame (src, flags); + meta_screen_cast_stream_src_maybe_record_frame (src, flags, NULL); } static void @@ -394,7 +394,7 @@ return; flags = META_SCREEN_CAST_RECORD_FLAG_CURSOR_ONLY; - meta_screen_cast_stream_src_maybe_record_frame (src, flags); + meta_screen_cast_stream_src_maybe_record_frame (src, flags, NULL); } static void @@ -477,7 +477,7 @@ } flags = META_SCREEN_CAST_RECORD_FLAG_NONE; - meta_screen_cast_stream_src_maybe_record_frame (src, flags); + meta_screen_cast_stream_src_maybe_record_frame (src, flags, NULL); } static void @@ -551,7 +551,7 @@ MetaScreenCastRecordFlag flags; flags = META_SCREEN_CAST_RECORD_FLAG_NONE; - meta_screen_cast_stream_src_maybe_record_frame (src, flags); + meta_screen_cast_stream_src_maybe_record_frame (src, flags, NULL); } static void diff -Nru mutter-44.0/src/backends/meta-stage.c mutter-44.1/src/backends/meta-stage.c --- mutter-44.0/src/backends/meta-stage.c 2023-03-19 10:55:05.000000000 +0000 +++ mutter-44.1/src/backends/meta-stage.c 2023-04-25 16:16:17.000000000 +0000 @@ -189,6 +189,7 @@ notify_watchers_for_mode (MetaStage *stage, ClutterStageView *view, ClutterPaintContext *paint_context, + ClutterFrame *frame, MetaStageWatchPhase watch_phase) { GPtrArray *watchers; @@ -203,7 +204,7 @@ if (watch->view && view != watch->view) continue; - watch->callback (stage, view, paint_context, watch->user_data); + watch->callback (stage, view, paint_context, frame, watch->user_data); } } @@ -214,7 +215,7 @@ { MetaStage *meta_stage = META_STAGE (stage); - notify_watchers_for_mode (meta_stage, view, NULL, + notify_watchers_for_mode (meta_stage, view, NULL, frame, META_STAGE_WATCH_BEFORE_PAINT); } @@ -224,13 +225,15 @@ { MetaStage *stage = META_STAGE (actor); ClutterStageView *view; + ClutterFrame *frame; CLUTTER_ACTOR_CLASS (meta_stage_parent_class)->paint (actor, paint_context); + frame = clutter_paint_context_get_frame (paint_context); view = clutter_paint_context_get_stage_view (paint_context); if (view) { - notify_watchers_for_mode (stage, view, paint_context, + notify_watchers_for_mode (stage, view, paint_context, frame, META_STAGE_WATCH_AFTER_ACTOR_PAINT); } @@ -260,7 +263,7 @@ if (view) { - notify_watchers_for_mode (stage, view, paint_context, + notify_watchers_for_mode (stage, view, paint_context, frame, META_STAGE_WATCH_AFTER_OVERLAY_PAINT); } } @@ -277,7 +280,7 @@ redraw_clip, frame); - notify_watchers_for_mode (meta_stage, view, NULL, + notify_watchers_for_mode (meta_stage, view, NULL, frame, META_STAGE_WATCH_AFTER_PAINT); } diff -Nru mutter-44.0/src/backends/meta-stage-impl.c mutter-44.1/src/backends/meta-stage-impl.c --- mutter-44.0/src/backends/meta-stage-impl.c 2023-03-19 10:55:05.000000000 +0000 +++ mutter-44.1/src/backends/meta-stage-impl.c 2023-04-25 16:16:17.000000000 +0000 @@ -454,6 +454,46 @@ return transformed_region; } +static gboolean +should_use_clipped_redraw (gboolean is_full_redraw, + gboolean has_buffer_age, + gboolean buffer_has_valid_damage_history, + ClutterDrawDebugFlag paint_debug_flags, + CoglFramebuffer *framebuffer, + ClutterStageWindow *stage_window) +{ + gboolean can_blit_sub_buffer; + gboolean can_use_clipped_redraw; + gboolean is_warmed_up; + + if (is_full_redraw) + return FALSE; + + if (paint_debug_flags & CLUTTER_DEBUG_DISABLE_CLIPPED_REDRAWS) + return FALSE; + + if (COGL_IS_OFFSCREEN (framebuffer)) + return TRUE; + + if (!buffer_has_valid_damage_history) + { + meta_topic (META_DEBUG_BACKEND, + "Invalid back buffer age: forcing full redraw"); + return FALSE; + } + + can_blit_sub_buffer = + cogl_clutter_winsys_has_feature (COGL_WINSYS_FEATURE_SWAP_REGION); + can_use_clipped_redraw = + _clutter_stage_window_can_clip_redraws (stage_window) && + (can_blit_sub_buffer || has_buffer_age); + /* Some drivers struggle to get going and produce some junk + * frames when starting up... */ + is_warmed_up = + cogl_onscreen_get_frame_counter (COGL_ONSCREEN (framebuffer)) > 3; + return is_warmed_up && can_use_clipped_redraw; +} + static void meta_stage_impl_redraw_view_primary (MetaStageImpl *stage_impl, ClutterStageView *stage_view, @@ -465,8 +505,8 @@ CoglFramebuffer *onscreen = clutter_stage_view_get_onscreen (stage_view); cairo_rectangle_int_t view_rect; gboolean is_full_redraw; - gboolean use_clipped_redraw = TRUE; - gboolean can_blit_sub_buffer; + gboolean use_clipped_redraw; + gboolean buffer_has_valid_damage_history = FALSE; gboolean has_buffer_age; gboolean swap_with_damage; cairo_region_t *redraw_clip; @@ -484,10 +524,6 @@ fb_width = cogl_framebuffer_get_width (fb); fb_height = cogl_framebuffer_get_height (fb); - can_blit_sub_buffer = - COGL_IS_ONSCREEN (onscreen) && - cogl_clutter_winsys_has_feature (COGL_WINSYS_FEATURE_SWAP_REGION); - has_buffer_age = COGL_IS_ONSCREEN (onscreen) && cogl_clutter_winsys_has_feature (COGL_WINSYS_FEATURE_BUFFER_AGE); @@ -505,26 +541,20 @@ if (has_buffer_age) { buffer_age = cogl_onscreen_get_buffer_age (COGL_ONSCREEN (onscreen)); - if (!clutter_damage_history_is_age_valid (damage_history, buffer_age)) - { - meta_topic (META_DEBUG_BACKEND, - "Invalid back buffer(age=%d): forcing full redraw", - buffer_age); - use_clipped_redraw = FALSE; - } + buffer_has_valid_damage_history = + clutter_damage_history_is_age_valid (damage_history, + buffer_age); } meta_get_clutter_debug_flags (NULL, &paint_debug_flags, NULL); use_clipped_redraw = - use_clipped_redraw && - !(paint_debug_flags & CLUTTER_DEBUG_DISABLE_CLIPPED_REDRAWS) && - _clutter_stage_window_can_clip_redraws (stage_window) && - (can_blit_sub_buffer || has_buffer_age) && - !is_full_redraw && - /* some drivers struggle to get going and produce some junk - * frames when starting up... */ - cogl_onscreen_get_frame_counter (COGL_ONSCREEN (onscreen)) > 3; + should_use_clipped_redraw (is_full_redraw, + has_buffer_age, + buffer_has_valid_damage_history, + paint_debug_flags, + onscreen, + stage_window); if (use_clipped_redraw) { diff -Nru mutter-44.0/src/backends/meta-stage-private.h mutter-44.1/src/backends/meta-stage-private.h --- mutter-44.0/src/backends/meta-stage-private.h 2023-03-19 10:55:05.000000000 +0000 +++ mutter-44.1/src/backends/meta-stage-private.h 2023-04-25 16:16:17.000000000 +0000 @@ -42,6 +42,7 @@ typedef void (* MetaStageWatchFunc) (MetaStage *stage, ClutterStageView *view, ClutterPaintContext *paint_context, + ClutterFrame *frame, gpointer user_data); ClutterActor *meta_stage_new (MetaBackend *backend); diff -Nru mutter-44.0/src/backends/native/meta-frame-native.c mutter-44.1/src/backends/native/meta-frame-native.c --- mutter-44.0/src/backends/native/meta-frame-native.c 2023-03-19 10:55:05.000000000 +0000 +++ mutter-44.1/src/backends/native/meta-frame-native.c 2023-04-25 16:16:17.000000000 +0000 @@ -30,6 +30,7 @@ ClutterFrame base; MetaKmsUpdate *kms_update; + gboolean had_kms_update; }; static void @@ -59,6 +60,7 @@ g_return_if_fail (!frame_native->kms_update); frame_native->kms_update = kms_update; + frame_native->had_kms_update = TRUE; } MetaKmsUpdate * @@ -73,6 +75,7 @@ } frame_native->kms_update = meta_kms_update_new (kms_device); + frame_native->had_kms_update = TRUE; return frame_native->kms_update; } @@ -87,3 +90,9 @@ { return !!frame_native->kms_update; } + +gboolean +meta_frame_native_had_kms_update (MetaFrameNative *frame_native) +{ + return frame_native->had_kms_update; +} diff -Nru mutter-44.0/src/backends/native/meta-frame-native.h mutter-44.1/src/backends/native/meta-frame-native.h --- mutter-44.0/src/backends/native/meta-frame-native.h 2023-03-19 10:55:05.000000000 +0000 +++ mutter-44.1/src/backends/native/meta-frame-native.h 2023-04-25 16:16:17.000000000 +0000 @@ -43,4 +43,7 @@ META_EXPORT_TEST gboolean meta_frame_native_has_kms_update (MetaFrameNative *frame_native); +META_EXPORT_TEST +gboolean meta_frame_native_had_kms_update (MetaFrameNative *frame_native); + #endif /* META_FRAME_NATIVE_H */ diff -Nru mutter-44.0/src/backends/native/meta-kms-crtc.c mutter-44.1/src/backends/native/meta-kms-crtc.c --- mutter-44.0/src/backends/native/meta-kms-crtc.c 2023-03-19 10:55:05.000000000 +0000 +++ mutter-44.1/src/backends/native/meta-kms-crtc.c 2023-04-25 16:16:17.000000000 +0000 @@ -170,12 +170,7 @@ { crtc_state->gamma.size = drm_crtc->gamma_size; crtc_state->gamma.supported = drm_crtc->gamma_size != 0; - crtc_state->gamma.value = meta_gamma_lut_new (drm_crtc->gamma_size, - NULL, NULL, NULL); - - crtc_state->gamma.value->red = g_new0 (uint16_t, drm_crtc->gamma_size); - crtc_state->gamma.value->green = g_new0 (uint16_t, drm_crtc->gamma_size); - crtc_state->gamma.value->blue = g_new0 (uint16_t, drm_crtc->gamma_size); + crtc_state->gamma.value = meta_gamma_lut_new_sized (drm_crtc->gamma_size); drmModeCrtcGetGamma (meta_kms_impl_device_get_fd (impl_device), crtc->id, diff -Nru mutter-44.0/src/backends/native/meta-kms-device.c mutter-44.1/src/backends/native/meta-kms-device.c --- mutter-44.0/src/backends/native/meta-kms-device.c 2023-03-19 10:55:05.000000000 +0000 +++ mutter-44.1/src/backends/native/meta-kms-device.c 2023-04-25 16:16:17.000000000 +0000 @@ -578,6 +578,9 @@ MetaKmsDevice *device = META_KMS_DEVICE (object); g_free (device->path); + g_free (device->driver_name); + g_free (device->driver_description); + g_list_free (device->fallback_modes); g_list_free (device->crtcs); g_list_free (device->connectors); g_list_free (device->planes); diff -Nru mutter-44.0/src/backends/native/meta-kms-impl-device.c mutter-44.1/src/backends/native/meta-kms-impl-device.c --- mutter-44.0/src/backends/native/meta-kms-impl-device.c 2023-03-19 10:55:05.000000000 +0000 +++ mutter-44.1/src/backends/native/meta-kms-impl-device.c 2023-04-25 16:16:17.000000000 +0000 @@ -1008,7 +1008,7 @@ MetaKmsImplDevicePrivate *priv = meta_kms_impl_device_get_instance_private (impl_device); MetaKms *kms = meta_kms_device_get_kms (priv->device); - GList *result_listeners; + g_autoptr (GList) result_listeners = NULL; GList *l; result_listeners = meta_kms_update_take_result_listeners (update); diff -Nru mutter-44.0/src/backends/native/meta-kms-impl-device-simple.c mutter-44.1/src/backends/native/meta-kms-impl-device-simple.c --- mutter-44.0/src/backends/native/meta-kms-impl-device-simple.c 2023-03-19 10:55:05.000000000 +0000 +++ mutter-44.1/src/backends/native/meta-kms-impl-device-simple.c 2023-04-25 16:16:17.000000000 +0000 @@ -1679,7 +1679,7 @@ g_clear_pointer (&impl_device_simple->mode_set_fallback_feedback_source, g_source_destroy); - g_hash_table_destroy (impl_device_simple->cached_mode_sets); + g_clear_pointer (&impl_device_simple->cached_mode_sets, g_hash_table_destroy); G_OBJECT_CLASS (meta_kms_impl_device_simple_parent_class)->finalize (object); } diff -Nru mutter-44.0/src/backends/native/meta-onscreen-native.c mutter-44.1/src/backends/native/meta-onscreen-native.c --- mutter-44.0/src/backends/native/meta-onscreen-native.c 2023-03-19 10:55:05.000000000 +0000 +++ mutter-44.1/src/backends/native/meta-onscreen-native.c 2023-04-25 16:16:17.000000000 +0000 @@ -1525,6 +1525,29 @@ } } +static void +on_finish_frame_update_result (const MetaKmsFeedback *kms_feedback, + gpointer user_data) +{ + CoglOnscreen *onscreen = COGL_ONSCREEN (user_data); + const GError *error; + CoglFrameInfo *frame_info; + + error = meta_kms_feedback_get_error (kms_feedback); + if (!error) + return; + + if (!g_error_matches (error, + G_IO_ERROR, + G_IO_ERROR_PERMISSION_DENIED)) + g_warning ("Cursor update failed: %s", error->message); + + frame_info = cogl_onscreen_peek_head_frame_info (onscreen); + frame_info->flags |= COGL_FRAME_INFO_FLAG_SYMBOLIC; + + meta_onscreen_native_notify_frame_complete (onscreen); +} + void meta_onscreen_native_finish_frame (CoglOnscreen *onscreen, ClutterFrame *frame) @@ -1544,6 +1567,10 @@ return; } + meta_kms_update_add_result_listener (kms_update, + on_finish_frame_update_result, + onscreen_native); + meta_kms_update_add_page_flip_listener (kms_update, kms_crtc, &page_flip_listener_vtable, diff -Nru mutter-44.0/src/backends/native/meta-output-kms.c mutter-44.1/src/backends/native/meta-output-kms.c --- mutter-44.0/src/backends/native/meta-output-kms.c 2023-03-19 10:55:05.000000000 +0000 +++ mutter-44.1/src/backends/native/meta-output-kms.c 2023-04-25 16:16:17.000000000 +0000 @@ -139,16 +139,26 @@ return connector_state->privacy_screen_state; } -static uint64_t -meta_output_kms_get_supported_color_spaces (MetaOutput *output) +static gboolean +meta_output_kms_is_color_space_supported (MetaOutput *output, + MetaOutputColorspace color_space) { MetaOutputKms *output_kms = META_OUTPUT_KMS (output); const MetaKmsConnectorState *connector_state; + const MetaOutputInfo *output_info; + + output_info = meta_output_get_info (output); + + if (!meta_output_info_is_color_space_supported (output_info, color_space)) + return FALSE; connector_state = meta_kms_connector_get_current_state (output_kms->kms_connector); - return connector_state->colorspace.supported; + if (!(connector_state->colorspace.supported & (1 << color_space))) + return FALSE; + + return TRUE; } static gboolean @@ -535,8 +545,8 @@ output_class->get_privacy_screen_state = meta_output_kms_get_privacy_screen_state; - output_class->get_supported_color_spaces = - meta_output_kms_get_supported_color_spaces; + output_class->is_color_space_supported = + meta_output_kms_is_color_space_supported; output_class->is_hdr_metadata_supported = meta_output_kms_is_hdr_metadata_supported; diff -Nru mutter-44.0/src/backends/x11/meta-input-settings-x11.c mutter-44.1/src/backends/x11/meta-input-settings-x11.c --- mutter-44.0/src/backends/x11/meta-input-settings-x11.c 2023-03-19 10:55:05.000000000 +0000 +++ mutter-44.1/src/backends/x11/meta-input-settings-x11.c 2023-04-25 16:16:17.000000000 +0000 @@ -170,6 +170,7 @@ int device_id; Atom property_atom; guchar *data_ret; + int err; property_atom = XInternAtom (xdisplay, property, True); if (!property_atom) @@ -181,8 +182,19 @@ if (!data_ret) return; + meta_clutter_x11_trap_x_errors (); XIChangeProperty (xdisplay, device_id, property_atom, type, format, XIPropModeReplace, data, nitems); + XSync (xdisplay, False); + err = meta_clutter_x11_untrap_x_errors (); + if (err) + { + g_warning ("XIChangeProperty failed on device %d property \"%s\" with X error %d", + device_id, + property, + err); + } + meta_XFree (data_ret); } diff -Nru mutter-44.0/src/backends/x11/meta-output-xrandr.c mutter-44.1/src/backends/x11/meta-output-xrandr.c --- mutter-44.0/src/backends/x11/meta-output-xrandr.c 2023-03-19 10:55:05.000000000 +0000 +++ mutter-44.1/src/backends/x11/meta-output-xrandr.c 2023-04-25 16:16:17.000000000 +0000 @@ -526,10 +526,10 @@ &nitems, &bytes_after, &buffer); if (actual_type != XA_INTEGER || actual_format != 32 || nitems < 1) - return FALSE; + return -1; value = ((int*)buffer)[0]; - if (value > 0) + if (value >= 0) return normalize_backlight (output, value); else return -1; diff -Nru mutter-44.0/src/backends/x11/nested/meta-backend-x11-nested.c mutter-44.1/src/backends/x11/nested/meta-backend-x11-nested.c --- mutter-44.0/src/backends/x11/nested/meta-backend-x11-nested.c 2023-03-19 10:55:05.000000000 +0000 +++ mutter-44.1/src/backends/x11/nested/meta-backend-x11-nested.c 2023-04-25 16:16:17.000000000 +0000 @@ -181,6 +181,13 @@ return FALSE; } +static void +meta_backend_x11_nested_set_pointer_constraint (MetaBackend *backend, + MetaPointerConstraint *constraint) +{ + g_debug ("Ignored pointer constraint in nested backend"); +} + static gboolean meta_backend_x11_nested_handle_host_xevent (MetaBackendX11 *x11, XEvent *event) @@ -320,6 +327,7 @@ backend_class->lock_layout_group = meta_backend_x11_nested_lock_layout_group; backend_class->set_keymap = meta_backend_x11_nested_set_keymap; backend_class->is_lid_closed = meta_backend_x11_nested_is_lid_closed; + backend_class->set_pointer_constraint = meta_backend_x11_nested_set_pointer_constraint; backend_x11_class->handle_host_xevent = meta_backend_x11_nested_handle_host_xevent; backend_x11_class->translate_device_event = meta_backend_x11_nested_translate_device_event; diff -Nru mutter-44.0/src/compositor/meta-dnd.c mutter-44.1/src/compositor/meta-dnd.c --- mutter-44.0/src/compositor/meta-dnd.c 2023-03-19 10:55:05.000000000 +0000 +++ mutter-44.1/src/compositor/meta-dnd.c 2023-04-25 16:16:17.000000000 +0000 @@ -280,6 +280,8 @@ MetaDndPrivate *priv = meta_dnd_get_instance_private (dnd); MetaWaylandDataDevice *data_device = data_device_from_dnd (dnd); + meta_wayland_data_device_set_dnd_source (data_device, NULL); + meta_wayland_data_device_unset_dnd_selection (data_device); meta_wayland_data_device_end_drag (data_device); priv->dnd_during_modal = FALSE; diff -Nru mutter-44.0/src/compositor/meta-window-actor-x11.c mutter-44.1/src/compositor/meta-window-actor-x11.c --- mutter-44.0/src/compositor/meta-window-actor-x11.c 2023-03-19 10:55:05.000000000 +0000 +++ mutter-44.1/src/compositor/meta-window-actor-x11.c 2023-04-25 16:16:17.000000000 +0000 @@ -723,7 +723,7 @@ for (x = rect.x; x < (rect.x + rect.width); x++) { int x2 = x; - while (mask_data[y * stride + x2] == 255 && x2 < (rect.x + rect.width)) + while (x2 < (rect.x + rect.width) && mask_data[y * stride + x2] == 255) x2++; if (x2 > x) diff -Nru mutter-44.0/src/compositor/meta-window-drag.c mutter-44.1/src/compositor/meta-window-drag.c --- mutter-44.0/src/compositor/meta-window-drag.c 2023-03-19 10:55:05.000000000 +0000 +++ mutter-44.1/src/compositor/meta-window-drag.c 2023-04-25 16:16:17.000000000 +0000 @@ -57,9 +57,10 @@ ClutterInputDevice *leading_device; ClutterEventSequence *leading_touch_sequence; + double anchor_rel_x; + double anchor_rel_y; int anchor_root_x; int anchor_root_y; - MetaRectangle anchor_window_pos; MetaTileMode tile_mode; int tile_monitor_number; int latest_motion_x; @@ -411,14 +412,6 @@ meta_window_drag_end (window_drag); } -static void -on_grab_window_size_changed (MetaWindow *window, - MetaWindowDrag *window_drag) -{ - meta_window_get_frame_rect (window, - &window_drag->anchor_window_pos); -} - static MetaWindow * get_first_freefloating_window (MetaWindow *window) { @@ -489,8 +482,6 @@ window_drag->anchor_root_y = *y; window_drag->latest_motion_x = *x; window_drag->latest_motion_y = *y; - meta_window_get_frame_rect (window, - &window_drag->anchor_window_pos); seat = clutter_backend_get_default_seat (clutter_get_default_backend ()); clutter_seat_warp_pointer (seat, *x, *y); @@ -1097,8 +1088,8 @@ if (window_drag->grab_op & META_GRAB_OP_WINDOW_FLAG_KEYBOARD) { - if ((window_drag->grab_op & META_GRAB_OP_KEYBOARD_MOVING) == - META_GRAB_OP_KEYBOARD_MOVING) + if ((window_drag->grab_op & (META_GRAB_OP_WINDOW_DIR_MASK | + META_GRAB_OP_WINDOW_FLAG_UNKNOWN)) == 0) { meta_topic (META_DEBUG_KEYBINDINGS, "Processing event for keyboard move"); @@ -1188,7 +1179,7 @@ MetaWindow *window; int dx, dy; int new_x, new_y; - MetaRectangle old; + MetaRectangle old, frame_rect; int shake_threshold; window = window_drag->effective_grab_window; @@ -1203,15 +1194,16 @@ dx = x - window_drag->anchor_root_x; dy = y - window_drag->anchor_root_y; - new_x = window_drag->anchor_window_pos.x + dx; - new_y = window_drag->anchor_window_pos.y + dy; + meta_window_get_frame_rect (window, &frame_rect); + new_x = x - (frame_rect.width * window_drag->anchor_rel_x); + new_y = y - (frame_rect.height * window_drag->anchor_rel_y); - meta_verbose ("x,y = %d,%d anchor ptr %d,%d anchor pos %d,%d dx,dy %d,%d", + meta_verbose ("x,y = %d,%d anchor ptr %d,%d rel anchor pos %f,%f dx,dy %d,%d", x, y, window_drag->anchor_root_x, window_drag->anchor_root_y, - window_drag->anchor_window_pos.x, - window_drag->anchor_window_pos.y, + window_drag->anchor_rel_x, + window_drag->anchor_rel_y, dx, dy); /* Don't bother doing anything if no move has been specified. (This @@ -1451,8 +1443,8 @@ dy *= 2; } - new_rect.width = window_drag->anchor_window_pos.width; - new_rect.height = window_drag->anchor_window_pos.height; + new_rect.width = window_drag->initial_window_pos.width; + new_rect.height = window_drag->initial_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 @@ -1850,13 +1842,6 @@ g_signal_connect (grab_window, "unmanaging", G_CALLBACK (on_grab_window_unmanaging), window_drag); - if (meta_grab_op_is_moving (grab_op)) - { - window_drag->size_changed_id = - g_signal_connect (grab_window, "size-changed", - G_CALLBACK (on_grab_window_size_changed), window_drag); - } - window_drag->leading_device = device; window_drag->leading_touch_sequence = sequence; window_drag->tile_mode = grab_window->tile_mode; @@ -1877,7 +1862,15 @@ meta_window_get_frame_rect (window_drag->effective_grab_window, &window_drag->initial_window_pos); - window_drag->anchor_window_pos = window_drag->initial_window_pos; + + window_drag->anchor_rel_x = + CLAMP ((double) (root_x - window_drag->initial_window_pos.x) / + window_drag->initial_window_pos.width, + 0, 1); + window_drag->anchor_rel_y = + CLAMP ((double) (root_y - window_drag->initial_window_pos.y) / + window_drag->initial_window_pos.height, + 0, 1); if (meta_is_wayland_compositor ()) { diff -Nru mutter-44.0/src/core/display-private.h mutter-44.1/src/core/display-private.h --- mutter-44.0/src/core/display-private.h 2023-03-19 10:55:05.000000000 +0000 +++ mutter-44.1/src/core/display-private.h 2023-04-25 16:16:17.000000000 +0000 @@ -237,9 +237,9 @@ void meta_display_reload_cursor (MetaDisplay *display); void meta_display_grab_window_buttons (MetaDisplay *display, - Window xwindow); + MetaWindow *window); void meta_display_ungrab_window_buttons (MetaDisplay *display, - Window xwindow); + MetaWindow *window); void meta_display_grab_focus_window_button (MetaDisplay *display, MetaWindow *window); diff -Nru mutter-44.0/src/core/frame.c mutter-44.1/src/core/frame.c --- mutter-44.0/src/core/frame.c 2023-03-19 10:55:05.000000000 +0000 +++ mutter-44.1/src/core/frame.c 2023-04-25 16:16:17.000000000 +0000 @@ -250,71 +250,6 @@ meta_window_queue (window, META_QUEUE_MOVE_RESIZE); } - -MetaFrameFlags -meta_frame_get_flags (MetaFrame *frame) -{ - MetaFrameFlags flags; - - flags = 0; - - if (frame->window->border_only) - { - ; /* FIXME this may disable the _function_ as well as decor - * in some cases, which is sort of wrong. - */ - } - else - { - flags |= META_FRAME_ALLOWS_MENU; - - if (frame->window->has_close_func) - flags |= META_FRAME_ALLOWS_DELETE; - - if (frame->window->has_maximize_func) - flags |= META_FRAME_ALLOWS_MAXIMIZE; - - if (frame->window->has_minimize_func) - flags |= META_FRAME_ALLOWS_MINIMIZE; - - } - - if (META_WINDOW_ALLOWS_MOVE (frame->window)) - flags |= META_FRAME_ALLOWS_MOVE; - - if (META_WINDOW_ALLOWS_HORIZONTAL_RESIZE (frame->window)) - flags |= META_FRAME_ALLOWS_HORIZONTAL_RESIZE; - - if (META_WINDOW_ALLOWS_VERTICAL_RESIZE (frame->window)) - flags |= META_FRAME_ALLOWS_VERTICAL_RESIZE; - - if (meta_window_appears_focused (frame->window)) - flags |= META_FRAME_HAS_FOCUS; - - if (frame->window->on_all_workspaces_requested) - flags |= META_FRAME_STUCK; - - /* FIXME: Should we have some kind of UI for windows that are just vertically - * maximized or just horizontally maximized? - */ - if (META_WINDOW_MAXIMIZED (frame->window)) - flags |= META_FRAME_MAXIMIZED; - - if (META_WINDOW_TILED_LEFT (frame->window)) - flags |= META_FRAME_TILED_LEFT; - - if (META_WINDOW_TILED_RIGHT (frame->window)) - flags |= META_FRAME_TILED_RIGHT; - - if (frame->window->fullscreen) - flags |= META_FRAME_FULLSCREEN; - - if (frame->window->wm_state_above) - flags |= META_FRAME_ABOVE; - - return flags; -} - void meta_frame_borders_clear (MetaFrameBorders *self) { diff -Nru mutter-44.0/src/core/frame.h mutter-44.1/src/core/frame.h --- mutter-44.0/src/core/frame.h 2023-03-19 10:55:05.000000000 +0000 +++ mutter-44.1/src/core/frame.h 2023-04-25 16:16:17.000000000 +0000 @@ -57,7 +57,6 @@ void meta_window_ensure_frame (MetaWindow *window); void meta_window_destroy_frame (MetaWindow *window); -MetaFrameFlags meta_frame_get_flags (MetaFrame *frame); Window meta_frame_get_xwindow (MetaFrame *frame); /* These should ONLY be called from meta_window_move_resize_internal */ diff -Nru mutter-44.0/src/core/keybindings.c mutter-44.1/src/core/keybindings.c --- mutter-44.0/src/core/keybindings.c 2023-03-19 10:55:05.000000000 +0000 +++ mutter-44.1/src/core/keybindings.c 2023-04-25 16:16:17.000000000 +0000 @@ -1176,22 +1176,27 @@ static void meta_change_button_grab (MetaKeyBindingManager *keys, - Window xwindow, - gboolean grab, - gboolean sync, - int button, - int modmask) + MetaWindow *window, + gboolean grab, + gboolean sync, + int button, + int modmask) { - if (meta_is_wayland_compositor ()) - return; - - MetaBackendX11 *backend = META_BACKEND_X11 (keys->backend); - Display *xdisplay = meta_backend_x11_get_xdisplay (backend); - + MetaBackendX11 *backend; + Display *xdisplay; unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 }; XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits }; + Window xwindow; GArray *mods; + if (meta_is_wayland_compositor ()) + return; + if (window->client_type != META_WINDOW_CLIENT_TYPE_X11) + return; + + backend = META_BACKEND_X11 (keys->backend); + xdisplay = meta_backend_x11_get_xdisplay (backend); + XISetMask (mask.mask, XI_ButtonPress); XISetMask (mask.mask, XI_ButtonRelease); XISetMask (mask.mask, XI_Motion); @@ -1200,6 +1205,11 @@ meta_clutter_x11_trap_x_errors (); + if (window->frame) + xwindow = window->frame->xwindow; + else + xwindow = window->xwindow; + /* GrabModeSync means freeze until XAllowEvents */ if (grab) XIGrabButton (xdisplay, @@ -1229,7 +1239,7 @@ static void meta_change_buttons_grab (MetaKeyBindingManager *keys, - Window xwindow, + MetaWindow *window, gboolean grab, gboolean sync, int modmask) @@ -1238,12 +1248,12 @@ int i; for (i = 1; i <= MAX_BUTTON; i++) - meta_change_button_grab (keys, xwindow, grab, sync, i, modmask); + meta_change_button_grab (keys, window, grab, sync, i, modmask); } void meta_display_grab_window_buttons (MetaDisplay *display, - Window xwindow) + MetaWindow *window) { MetaKeyBindingManager *keys = &display->key_binding_manager; @@ -1252,7 +1262,7 @@ * Grab Alt + button3 for popping up window menu. * Grab Alt + Shift + button1 for snap-moving window. */ - meta_verbose ("Grabbing window buttons for 0x%lx", xwindow); + meta_verbose ("Grabbing window buttons for %s", window->desc); /* FIXME If we ignored errors here instead of spewing, we could * put one big error trap around the loop and avoid a bunch of @@ -1261,7 +1271,7 @@ if (keys->window_grab_modifiers != 0) { - meta_change_buttons_grab (keys, xwindow, TRUE, FALSE, + meta_change_buttons_grab (keys, window, TRUE, FALSE, keys->window_grab_modifiers); /* In addition to grabbing Alt+Button1 for moving the window, @@ -1270,7 +1280,7 @@ * Shift+Alt+Button1 for some reason; so at least part of the * order still matters, which sucks (please FIXME). */ - meta_change_button_grab (keys, xwindow, + meta_change_button_grab (keys, window, TRUE, FALSE, 1, keys->window_grab_modifiers | ShiftMask); @@ -1279,14 +1289,14 @@ void meta_display_ungrab_window_buttons (MetaDisplay *display, - Window xwindow) + MetaWindow *window) { MetaKeyBindingManager *keys = &display->key_binding_manager; if (keys->window_grab_modifiers == 0) return; - meta_change_buttons_grab (keys, xwindow, FALSE, FALSE, + meta_change_buttons_grab (keys, window, FALSE, FALSE, keys->window_grab_modifiers); } @@ -1327,7 +1337,7 @@ * XSync() */ - meta_change_buttons_grab (keys, window->xwindow, TRUE, TRUE, XIAnyModifier); + meta_change_buttons_grab (keys, window, TRUE, TRUE, XIAnyModifier); window->have_focus_click_grab = TRUE; } @@ -1342,7 +1352,7 @@ if (!window->have_focus_click_grab) return; - meta_change_buttons_grab (keys, window->xwindow, FALSE, FALSE, XIAnyModifier); + meta_change_buttons_grab (keys, window, FALSE, FALSE, XIAnyModifier); window->have_focus_click_grab = FALSE; } @@ -1374,7 +1384,7 @@ for (l = windows; l; l = l->next) { MetaWindow *w = l->data; - meta_display_ungrab_window_buttons (display, w->xwindow); + meta_display_ungrab_window_buttons (display, w); } update_window_grab_modifiers (display); @@ -1383,7 +1393,7 @@ { MetaWindow *w = l->data; if (w->type != META_WINDOW_DOCK) - meta_display_grab_window_buttons (display, w->xwindow); + meta_display_grab_window_buttons (display, w); } g_slist_free (windows); diff -Nru mutter-44.0/src/core/meta-context-main.c mutter-44.1/src/core/meta-context-main.c --- mutter-44.0/src/core/meta-context-main.c 2023-03-19 10:55:05.000000000 +0000 +++ mutter-44.1/src/core/meta-context-main.c 2023-04-25 16:16:17.000000000 +0000 @@ -533,12 +533,9 @@ { MetaContextMain *context_main = user_data; int width, height; - float refresh_rate = 60.0; + float refresh_rate; - if (sscanf (value, "%dx%d@%f", - &width, &height, &refresh_rate) == 3 || - sscanf (value, "%dx%d", - &width, &height) == 2) + if (meta_parse_monitor_mode (value, &width, &height, &refresh_rate, 60.0)) { g_autofree char *serial = NULL; MetaVirtualMonitorInfo *virtual_monitor; diff -Nru mutter-44.0/src/core/window.c mutter-44.1/src/core/window.c --- mutter-44.0/src/core/window.c 2023-03-19 10:55:05.000000000 +0000 +++ mutter-44.1/src/core/window.c 2023-04-25 16:16:17.000000000 +0000 @@ -1691,15 +1691,14 @@ } gboolean -meta_window_should_be_showing (MetaWindow *window) +meta_window_should_be_showing_on_workspace (MetaWindow *window, + MetaWorkspace *workspace) { - MetaWorkspaceManager *workspace_manager = window->display->workspace_manager; - #ifdef HAVE_WAYLAND - if (window->client_type == META_WINDOW_CLIENT_TYPE_WAYLAND) + if (meta_is_wayland_compositor ()) { MetaWaylandSurface *surface = meta_window_get_wayland_surface (window); - if (!meta_wayland_surface_get_buffer (surface)) + if (!surface || !meta_wayland_surface_get_buffer (surface)) return FALSE; } #endif @@ -1709,11 +1708,20 @@ return FALSE; /* Windows should be showing if they're located on the - * active workspace and they're showing on their own workspace. */ - return (meta_window_located_on_workspace (window, workspace_manager->active_workspace) && + * workspace and they're showing on their own workspace. */ + return (meta_window_located_on_workspace (window, workspace) && meta_window_showing_on_its_workspace (window)); } +gboolean +meta_window_should_be_showing (MetaWindow *window) +{ + MetaWorkspaceManager *workspace_manager = window->display->workspace_manager; + MetaWorkspace *active_workspace = workspace_manager->active_workspace; + + return meta_window_should_be_showing_on_workspace (window, active_workspace); +} + static void implement_showing (MetaWindow *window, gboolean showing) @@ -5194,7 +5202,7 @@ meta_display_ungrab_focus_window_button (window->display, window); /* Since we ungrab with XIAnyModifier above, all button grabs go way so we need to re-grab the window buttons. */ - meta_display_grab_window_buttons (window->display, window->xwindow); + meta_display_grab_window_buttons (window->display, window); } g_signal_emit (window, window_signals[FOCUS], 0); diff -Nru mutter-44.0/src/core/window-private.h mutter-44.1/src/core/window-private.h --- mutter-44.0/src/core/window-private.h 2023-03-19 10:55:05.000000000 +0000 +++ mutter-44.1/src/core/window-private.h 2023-04-25 16:16:17.000000000 +0000 @@ -669,6 +669,9 @@ int h, MetaGravity gravity); +gboolean meta_window_should_be_showing_on_workspace (MetaWindow *window, + MetaWorkspace *workspace); + /* Return whether the window should be currently mapped */ gboolean meta_window_should_be_showing (MetaWindow *window); @@ -850,8 +853,6 @@ void meta_window_hide_close_dialog (MetaWindow *window); void meta_window_ensure_close_dialog_timeout (MetaWindow *window); -gboolean meta_window_has_pointer (MetaWindow *window); - void meta_window_emit_size_changed (MetaWindow *window); MetaPlacementRule *meta_window_get_placement_rule (MetaWindow *window); diff -Nru mutter-44.0/src/core/workspace.c mutter-44.1/src/core/workspace.c --- mutter-44.0/src/core/workspace.c 2023-03-19 10:55:05.000000000 +0000 +++ mutter-44.1/src/core/workspace.c 2023-04-25 16:16:17.000000000 +0000 @@ -1436,8 +1436,7 @@ window->unmaps_pending == 0 && window->type != META_WINDOW_DOCK && meta_window_is_focusable (window) && - meta_window_located_on_workspace (window, workspace) && - meta_window_showing_on_its_workspace (window); + meta_window_should_be_showing_on_workspace (window, workspace); } static gboolean diff -Nru mutter-44.0/src/frames/main.c mutter-44.1/src/frames/main.c --- mutter-44.0/src/frames/main.c 2023-03-19 10:55:05.000000000 +0000 +++ mutter-44.1/src/frames/main.c 2023-04-25 16:16:17.000000000 +0000 @@ -42,6 +42,8 @@ GMainLoop *loop; Display *xdisplay; + g_setenv ("GSK_RENDERER", "cairo", TRUE); + /* We do know the desired GDK backend, don't let * anyone tell us otherwise. */ diff -Nru mutter-44.0/src/frames/meta-frame.c mutter-44.1/src/frames/meta-frame.c --- mutter-44.0/src/frames/meta-frame.c 2023-03-19 10:55:05.000000000 +0000 +++ mutter-44.1/src/frames/meta-frame.c 2023-04-25 16:16:17.000000000 +0000 @@ -34,6 +34,8 @@ Atom atom__NET_WM_VISIBLE_NAME; Atom atom__NET_WM_NAME; Atom atom__MOTIF_WM_HINTS; + Atom atom__NET_WM_STATE; + Atom atom__NET_WM_STATE_FULLSCREEN; char *net_wm_visible_name; char *net_wm_name; @@ -73,6 +75,10 @@ gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_NAME"); frame->atom__MOTIF_WM_HINTS = gdk_x11_get_xatom_by_name_for_display (display, "_MOTIF_WM_HINTS"); + frame->atom__NET_WM_STATE = + gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE"); + frame->atom__NET_WM_STATE_FULLSCREEN = + gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE_FULLSCREEN"); G_OBJECT_CLASS (meta_frame_parent_class)->constructed (object); } @@ -151,7 +157,7 @@ { GdkDisplay *display = gtk_widget_get_display (GTK_WIDGET (window)); GtkWidget *content; - XClientMessageEvent ev; + XClientMessageEvent ev = { 0 }; Window client_xwindow; Atom delete_window_atom; @@ -463,12 +469,44 @@ gtk_window_set_resizable (frame, resizable); } +static void +frame_sync_wm_state (MetaFrame *frame, + Window client_window) +{ + GdkDisplay *display = gtk_widget_get_display (GTK_WIDGET (frame)); + Display *xdisplay = gdk_x11_display_get_xdisplay (display); + Atom *data = NULL, type; + int format; + unsigned long i, nitems, bytes_after; + + gdk_x11_display_error_trap_push (display); + + XGetWindowProperty (xdisplay, + client_window, + frame->atom__NET_WM_STATE, + 0, 32, + False, XA_ATOM, + &type, &format, + &nitems, &bytes_after, + (unsigned char **) &data); + + for (i = 0; i < nitems; i++) + { + if (data[i] == frame->atom__NET_WM_STATE_FULLSCREEN) + gtk_window_fullscreen (GTK_WINDOW (frame)); + } + + gdk_x11_display_error_trap_pop_ignored (display); + + XFree (data); +} + GtkWidget * meta_frame_new (Window window) { GtkWidget *frame, *header, *content; GdkSurface *surface; - int frame_height; + int frame_height = 0; double scale; frame = g_object_new (META_TYPE_FRAME, NULL); @@ -487,10 +525,15 @@ surface = gtk_native_get_surface (GTK_NATIVE (frame)); gdk_x11_surface_set_frame_sync_enabled (surface, TRUE); - gtk_widget_measure (header, - GTK_ORIENTATION_VERTICAL, 1, - &frame_height, - NULL, NULL, NULL); + frame_sync_wm_state (META_FRAME (frame), window); + + if (!gtk_window_is_fullscreen (GTK_WINDOW (frame))) + { + gtk_widget_measure (header, + GTK_ORIENTATION_VERTICAL, 1, + &frame_height, + NULL, NULL, NULL); + } scale = gdk_surface_get_scale_factor (gtk_native_get_surface (GTK_NATIVE (frame))); diff -Nru mutter-44.0/src/frames/meta-frame-content.c mutter-44.1/src/frames/meta-frame-content.c --- mutter-44.0/src/frames/meta-frame-content.c 2023-03-19 10:55:05.000000000 +0000 +++ mutter-44.1/src/frames/meta-frame-content.c 2023-04-25 16:16:17.000000000 +0000 @@ -118,12 +118,13 @@ { MetaFrameContent *content = META_FRAME_CONTENT (widget); GtkWindow *window = GTK_WINDOW (gtk_widget_get_root (widget)); - double x = 0, y = 0, scale; + graphene_point_t point = {}; + double scale; - gtk_widget_translate_coordinates (widget, - GTK_WIDGET (window), - x, y, - &x, &y); + if (!gtk_widget_compute_point (widget, + GTK_WIDGET (window), + &point, &point)) + return; scale = gdk_surface_get_scale_factor (gtk_native_get_surface (GTK_NATIVE (window))); @@ -132,8 +133,8 @@ * are ever other than 0. */ (GtkBorder) { - x * scale, 0, - y * scale, 0, + point.x * scale, 0, + point.y * scale, 0, }); } diff -Nru mutter-44.0/src/frames/meta-window-tracker.c mutter-44.1/src/frames/meta-window-tracker.c --- mutter-44.0/src/frames/meta-window-tracker.c 2023-03-19 10:55:05.000000000 +0000 +++ mutter-44.1/src/frames/meta-window-tracker.c 2023-04-25 16:16:17.000000000 +0000 @@ -341,6 +341,7 @@ XSelectInput (xdisplay, xroot, KeyPressMask | PropertyChangeMask | + StructureNotifyMask | SubstructureNotifyMask); g_signal_connect (display, "xevent", diff -Nru mutter-44.0/src/meta/window.h mutter-44.1/src/meta/window.h --- mutter-44.0/src/meta/window.h 2023-03-19 10:55:05.000000000 +0000 +++ mutter-44.1/src/meta/window.h 2023-04-25 16:16:17.000000000 +0000 @@ -443,4 +443,7 @@ META_EXPORT MetaWindowClientType meta_window_get_client_type (MetaWindow *window); +META_EXPORT +gboolean meta_window_has_pointer (MetaWindow *window); + #endif diff -Nru mutter-44.0/src/tests/kvm/run-kvm-test.sh mutter-44.1/src/tests/kvm/run-kvm-test.sh --- mutter-44.0/src/tests/kvm/run-kvm-test.sh 2023-03-19 10:55:05.000000000 +0000 +++ mutter-44.1/src/tests/kvm/run-kvm-test.sh 2023-04-25 16:16:17.000000000 +0000 @@ -1,4 +1,4 @@ -#!/usr/bin/bash +#!/bin/bash set -e diff -Nru mutter-44.0/src/tests/kvm/virtme-run.sh mutter-44.1/src/tests/kvm/virtme-run.sh --- mutter-44.0/src/tests/kvm/virtme-run.sh 2023-03-19 10:55:05.000000000 +0000 +++ mutter-44.1/src/tests/kvm/virtme-run.sh 2023-04-25 16:16:17.000000000 +0000 @@ -1,4 +1,4 @@ -#!/usr/bin/bash +#!/bin/bash set -e diff -Nru mutter-44.0/src/tests/meson.build mutter-44.1/src/tests/meson.build --- mutter-44.0/src/tests/meson.build 2023-03-19 10:55:05.000000000 +0000 +++ mutter-44.1/src/tests/meson.build 2023-04-25 16:16:17.000000000 +0000 @@ -409,6 +409,14 @@ ], 'variants': kms_test_variants, }, + { + 'name': 'kms-cursor-hotplug', + 'suite': 'backends/native', + 'sources': [ + 'native-kms-cursor-hotplug.c', + wayland_test_utils, + ], + }, ] privileged_test_cases += kms_test_cases diff -Nru mutter-44.0/src/tests/meta-ref-test.c mutter-44.1/src/tests/meta-ref-test.c --- mutter-44.0/src/tests/meta-ref-test.c 2023-03-19 10:55:05.000000000 +0000 +++ mutter-44.1/src/tests/meta-ref-test.c 2023-04-25 16:16:17.000000000 +0000 @@ -273,6 +273,7 @@ on_after_paint (MetaStage *stage, ClutterStageView *view, ClutterPaintContext *paint_context, + ClutterFrame *frame, gpointer user_data) { CaptureViewData *data = user_data; diff -Nru mutter-44.0/src/tests/monitor-configs/kms-cursor-hotplug-off.xml mutter-44.1/src/tests/monitor-configs/kms-cursor-hotplug-off.xml --- mutter-44.0/src/tests/monitor-configs/kms-cursor-hotplug-off.xml 1970-01-01 00:00:00.000000000 +0000 +++ mutter-44.1/src/tests/monitor-configs/kms-cursor-hotplug-off.xml 2023-04-25 16:16:17.000000000 +0000 @@ -0,0 +1,30 @@ + + + + 0 + 0 + yes + + + Meta-0 + MetaTestVendor + MetaVirtualMonitor + 0x1234 + + + 100 + 100 + 60 + + + + + + Virtual-1 + unknown + unknown + unknown + + + + diff -Nru mutter-44.0/src/tests/monitor-configs/kms-cursor-hotplug-on.xml mutter-44.1/src/tests/monitor-configs/kms-cursor-hotplug-on.xml --- mutter-44.0/src/tests/monitor-configs/kms-cursor-hotplug-on.xml 1970-01-01 00:00:00.000000000 +0000 +++ mutter-44.1/src/tests/monitor-configs/kms-cursor-hotplug-on.xml 2023-04-25 16:16:17.000000000 +0000 @@ -0,0 +1,40 @@ + + + + 0 + 0 + yes + + + Virtual-1 + unknown + unknown + unknown + + + 1024 + 768 + 60.003841 + + + + + 1024 + 0 + no + + + Meta-0 + MetaTestVendor + MetaVirtualMonitor + 0x1234 + + + 100 + 100 + 60 + + + + + diff -Nru mutter-44.0/src/tests/monitor-util-tests.c mutter-44.1/src/tests/monitor-util-tests.c --- mutter-44.0/src/tests/monitor-util-tests.c 2023-03-19 10:55:05.000000000 +0000 +++ mutter-44.1/src/tests/monitor-util-tests.c 2023-04-25 16:16:17.000000000 +0000 @@ -130,6 +130,85 @@ } } +static void +meta_test_monitor_parse_mode (void) +{ + const float fallback_refresh_rate = 60.0; + struct { + const char *string; + + gboolean expected_pass; + int expected_width; + int expected_height; + float expected_refresh_rate; + } test_cases[] = { + { + .string = "800x600", + .expected_pass = TRUE, + .expected_width = 800, + .expected_height = 600, + .expected_refresh_rate = fallback_refresh_rate, + }, + { + .string = "1280x720@30", + .expected_pass = TRUE, + .expected_width = 1280, + .expected_height = 720, + .expected_refresh_rate = 30.0, + }, + { + .string = "1920x1080@120.50", + .expected_pass = TRUE, + .expected_width = 1920, + .expected_height = 1080, + .expected_refresh_rate = 120.5, + }, + { + .string = "800X600", + .expected_pass = FALSE, + }, + { + .string = "800x", + .expected_pass = FALSE, + }, + { + .string = "800x600@", + .expected_pass = FALSE, + }, + { + .string = "800x600@notanumber", + .expected_pass = FALSE, + }, + { + .string = "nonsense", + .expected_pass = FALSE, + }, + }; + int i; + + for (i = 0; i < G_N_ELEMENTS (test_cases); i++) + { + int width, height; + float refresh_rate; + + if (meta_parse_monitor_mode (test_cases[i].string, + &width, &height, &refresh_rate, + fallback_refresh_rate)) + { + g_assert_true (test_cases[i].expected_pass); + g_assert_cmpint (width, ==, test_cases[i].expected_width); + g_assert_cmpint (height, ==, test_cases[i].expected_height); + g_assert_cmpfloat_with_epsilon (refresh_rate, + test_cases[i].expected_refresh_rate, + FLT_EPSILON); + } + else + { + g_assert_false (test_cases[i].expected_pass); + } + } +} + int main (int argc, char **argv) @@ -138,6 +217,8 @@ g_test_add_func ("/backends/monitor/spec/similar-size", meta_test_monitor_mode_spec_similar_size); + g_test_add_func ("/backends/monitor/parse-mode", + meta_test_monitor_parse_mode); return g_test_run (); } diff -Nru mutter-44.0/src/tests/native-kms-cursor-hotplug.c mutter-44.1/src/tests/native-kms-cursor-hotplug.c --- mutter-44.0/src/tests/native-kms-cursor-hotplug.c 1970-01-01 00:00:00.000000000 +0000 +++ mutter-44.1/src/tests/native-kms-cursor-hotplug.c 2023-04-25 16:16:17.000000000 +0000 @@ -0,0 +1,166 @@ +/* + * Copyright (C) 2022 Red Hat Inc. + * + * 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. + * + */ + +#include "config.h" + +#include "backends/meta-monitor-config-manager.h" +#include "backends/meta-virtual-monitor.h" +#include "core/window-private.h" +#include "meta-test/meta-context-test.h" +#include "meta/meta-backend.h" +#include "meta/meta-cursor-tracker.h" +#include "tests/meta-test-utils.h" +#include "tests/meta-wayland-test-driver.h" +#include "tests/meta-wayland-test-utils.h" +#include "tests/native-screen-cast.h" +#include "tests/native-virtual-monitor.h" +#include "wayland/meta-cursor-sprite-wayland.h" +#include "wayland/meta-wayland-private.h" +#include "wayland/meta-wayland-seat.h" + +static MetaContext *test_context; + +static void +meta_test_cursor_hotplug (void) +{ + MetaBackend *backend = meta_context_get_backend (test_context); + MetaMonitorManager *monitor_manager = + meta_backend_get_monitor_manager (backend); + MetaCursorRenderer *cursor_renderer = meta_backend_get_cursor_renderer (backend); + MetaWaylandCompositor *wayland_compositor = + meta_context_get_wayland_compositor (test_context); + MetaWaylandSeat *wayland_seat = wayland_compositor->seat; + g_autoptr (MetaWaylandTestDriver) test_driver = NULL; + MetaCursorSprite *cursor_sprite; + g_autoptr (MetaVirtualMonitorInfo) monitor_info = NULL; + MetaVirtualMonitor *virtual_monitor; + ClutterSeat *seat; + g_autoptr (ClutterVirtualInputDevice) virtual_pointer = NULL; + MetaWaylandTestClient *test_client; + MetaWindow *window; + GError *error = NULL; + + test_driver = meta_wayland_test_driver_new (wayland_compositor); + + seat = meta_backend_get_default_seat (backend); + virtual_pointer = clutter_seat_create_virtual_device (seat, + CLUTTER_POINTER_DEVICE); + + meta_set_custom_monitor_config_full (backend, "kms-cursor-hotplug-off.xml", + META_MONITORS_CONFIG_FLAG_NONE); + + monitor_info = meta_virtual_monitor_info_new (100, 100, 60.0, + "MetaTestVendor", + "MetaVirtualMonitor", + "0x1234"); + virtual_monitor = meta_monitor_manager_create_virtual_monitor (monitor_manager, + monitor_info, + &error); + if (!virtual_monitor) + g_error ("Failed to create virtual monitor: %s", error->message); + meta_monitor_manager_reload (monitor_manager); + + clutter_virtual_input_device_notify_absolute_motion (virtual_pointer, + g_get_monotonic_time (), + 50, 50); + + test_client = meta_wayland_test_client_new (test_context, + "kms-cursor-hotplug-helper"); + if (!test_client) + g_error ("Failed to launch test client: %s", error->message); + + while (TRUE) + { + window = meta_find_window_from_title (test_context, + "kms-cursor-hotplug-helper"); + if (window && window->visible_to_compositor) + break; + g_main_context_iteration (NULL, TRUE); + } + + meta_window_move_frame (window, FALSE, 0, 0); + meta_wait_for_paint (test_context); + + cursor_renderer = meta_backend_get_cursor_renderer (backend); + + while (TRUE) + { + cursor_sprite = meta_cursor_renderer_get_cursor (cursor_renderer); + if (cursor_sprite) + break; + g_main_context_iteration (NULL, TRUE); + } + g_assert_true (META_IS_CURSOR_SPRITE_WAYLAND (cursor_sprite)); + + /* + * This tests a particular series of events: + * + * 1) Unplug the mouse + * 2) Client attaches a new cursor buffer + * 3) Client destroys cursor surface + * 4) Monitor hotplug + * + * This would cause a NULL pointer deference when getting the buffer from the + * cursor surface when trying to realize the hardware cursor buffer on the + * hotplugged monitor. + */ + + g_clear_object (&virtual_pointer); + while (!(wayland_seat->capabilities & WL_SEAT_CAPABILITY_POINTER)) + g_main_context_iteration (NULL, TRUE); + + meta_wayland_test_driver_emit_sync_event (test_driver, 0); + meta_wayland_test_driver_wait_for_sync_point (test_driver, 0); + + meta_set_custom_monitor_config_full (backend, "kms-cursor-hotplug-on.xml", + META_MONITORS_CONFIG_FLAG_NONE); + meta_monitor_manager_reload (monitor_manager); + meta_wait_for_paint (test_context); + + meta_wayland_test_driver_emit_sync_event (test_driver, 1); + meta_wayland_test_client_finish (test_client); +} + +static void +init_tests (void) +{ + g_test_add_func ("/wayland/cursor-hotplug", + meta_test_cursor_hotplug); +} + +int +main (int argc, + char **argv) +{ + g_autoptr (MetaContext) context = NULL; + + context = meta_create_test_context (META_CONTEXT_TEST_TYPE_VKMS, + META_CONTEXT_TEST_FLAG_NO_X11 | + META_CONTEXT_TEST_FLAG_TEST_CLIENT); + g_assert (meta_context_configure (context, &argc, &argv, NULL)); + + test_context = context; + + init_tests (); + + return meta_context_test_run_tests (META_CONTEXT_TEST (context), + META_TEST_RUN_FLAG_NONE); +} + diff -Nru mutter-44.0/src/tests/stacking/closed-transient-only-take-focus-parents.metatest mutter-44.1/src/tests/stacking/closed-transient-only-take-focus-parents.metatest --- mutter-44.0/src/tests/stacking/closed-transient-only-take-focus-parents.metatest 2023-03-19 10:55:05.000000000 +0000 +++ mutter-44.1/src/tests/stacking/closed-transient-only-take-focus-parents.metatest 2023-04-25 16:16:17.000000000 +0000 @@ -9,7 +9,7 @@ accept_take_focus 1/1 true show 1/1 -create 1/2 csd +create 1/2 set_parent 1/2 1 accept_focus 1/2 false can_take_focus 1/2 true diff -Nru mutter-44.0/src/tests/wayland-test-clients/kms-cursor-hotplug-helper.c mutter-44.1/src/tests/wayland-test-clients/kms-cursor-hotplug-helper.c --- mutter-44.0/src/tests/wayland-test-clients/kms-cursor-hotplug-helper.c 1970-01-01 00:00:00.000000000 +0000 +++ mutter-44.1/src/tests/wayland-test-clients/kms-cursor-hotplug-helper.c 2023-04-25 16:16:17.000000000 +0000 @@ -0,0 +1,286 @@ +/* + * Copyright (C) 2023 Red Hat Inc. + * + * 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, see . + */ + +#include "config.h" + +#include +#include +#include + +#include "wayland-test-client-utils.h" + +static WaylandDisplay *display; + +static struct wl_registry *wl_registry; +static struct wl_seat *wl_seat; +static struct wl_pointer *wl_pointer; +static uint32_t enter_serial; + +static struct wl_surface *surface; +static struct xdg_surface *xdg_surface; +static struct xdg_toplevel *xdg_toplevel; +struct wl_surface *cursor_surface; +struct wl_cursor_theme *cursor_theme; +struct wl_cursor *cursor; +struct wl_cursor *cursor2; + +static gboolean running; + +static void +init_surface (void) +{ + xdg_toplevel_set_title (xdg_toplevel, "kms-cursor-hotplug-helper"); + wl_surface_commit (surface); +} + +static void +draw_main (int width, + int height) +{ + draw_surface (display, surface, width, height, 0xff00ff00); +} + +static void +handle_xdg_toplevel_configure (void *data, + struct xdg_toplevel *xdg_toplevel, + int32_t width, + int32_t height, + struct wl_array *state) +{ +} + +static void +handle_xdg_toplevel_close (void *data, + struct xdg_toplevel *xdg_toplevel) +{ + g_assert_not_reached (); +} + +static void +handle_xdg_toplevel_configure_bounds (void *data, + struct xdg_toplevel *xdg_toplevel, + int32_t bounds_width, + int32_t bounds_height) +{ +} + +static const struct xdg_toplevel_listener xdg_toplevel_listener = { + handle_xdg_toplevel_configure, + handle_xdg_toplevel_close, + handle_xdg_toplevel_configure_bounds, +}; + +static void +handle_xdg_surface_configure (void *data, + struct xdg_surface *xdg_surface, + uint32_t serial) +{ + draw_main (100, 100); + xdg_surface_ack_configure (xdg_surface, serial); + wl_surface_commit (surface); +} + +static const struct xdg_surface_listener xdg_surface_listener = { + handle_xdg_surface_configure, +}; + + +static void +pointer_handle_enter (void *data, + struct wl_pointer *pointer, + uint32_t serial, + struct wl_surface *surface, + wl_fixed_t sx, + wl_fixed_t sy) +{ + struct wl_buffer *buffer; + struct wl_cursor_image *image; + + image = cursor->images[0]; + buffer = wl_cursor_image_get_buffer (image); + + enter_serial = serial; + wl_pointer_set_cursor (pointer, serial, + cursor_surface, + image->hotspot_x, + image->hotspot_y); + wl_surface_attach (cursor_surface, buffer, 0, 0); + wl_surface_damage (cursor_surface, 0, 0, + image->width, image->height); + wl_surface_commit (cursor_surface); +} + +static void +pointer_handle_leave (void *data, + struct wl_pointer *pointer, + uint32_t serial, + struct wl_surface *surface) +{ +} + +static void +pointer_handle_motion (void *data, + struct wl_pointer *pointer, + uint32_t time, + wl_fixed_t sx, + wl_fixed_t sy) +{ +} + +static void +pointer_handle_button (void *data, + struct wl_pointer *pointer, + uint32_t serial, + uint32_t time, + uint32_t button, + uint32_t state) +{ +} + +static void +pointer_handle_axis (void *data, + struct wl_pointer *pointer, + uint32_t time, + uint32_t axis, + wl_fixed_t value) +{ +} + +static const struct wl_pointer_listener pointer_listener = { + pointer_handle_enter, + pointer_handle_leave, + pointer_handle_motion, + pointer_handle_button, + pointer_handle_axis, +}; + +static void +seat_handle_capabilities (void *data, + struct wl_seat *wl_seat, + enum wl_seat_capability caps) +{ + if (caps & WL_SEAT_CAPABILITY_POINTER) + { + wl_pointer = wl_seat_get_pointer (wl_seat); + wl_pointer_add_listener (wl_pointer, &pointer_listener, NULL); + } +} + +static void +seat_handle_name (void *data, + struct wl_seat *seat, + const char *name) +{ +} + +static const struct wl_seat_listener seat_listener = { + seat_handle_capabilities, + seat_handle_name, +}; + +static void +handle_registry_global (void *data, + struct wl_registry *registry, + uint32_t id, + const char *interface, + uint32_t version) +{ + if (strcmp (interface, "wl_seat") == 0) + { + wl_seat = wl_registry_bind (registry, id, + &wl_seat_interface, + 1); + wl_seat_add_listener (wl_seat, &seat_listener, NULL); + } +} + +static void +handle_registry_global_remove (void *data, + struct wl_registry *registry, + uint32_t name) +{ +} + +static const struct wl_registry_listener registry_listener = { + handle_registry_global, + handle_registry_global_remove +}; + +static void +on_sync_event (WaylandDisplay *display, + uint32_t serial) +{ + if (serial == 1) + { + running = FALSE; + } + else if (serial == 0) + { + struct wl_buffer *buffer; + struct wl_cursor_image *image; + + image = cursor2->images[0]; + buffer = wl_cursor_image_get_buffer (image); + + wl_surface_attach (cursor_surface, buffer, 0, 0); + wl_surface_damage (cursor_surface, 0, 0, + image->width, image->height); + wl_surface_commit (cursor_surface); + + wl_surface_destroy (cursor_surface); + + test_driver_sync_point (display->test_driver, 0, NULL); + } +} + +int +main (int argc, + char **argv) +{ + display = wayland_display_new (WAYLAND_DISPLAY_CAPABILITY_TEST_DRIVER); + wl_registry = wl_display_get_registry (display->display); + wl_registry_add_listener (wl_registry, ®istry_listener, display); + wl_display_roundtrip (display->display); + + g_signal_connect (display, "sync-event", G_CALLBACK (on_sync_event), NULL); + + surface = wl_compositor_create_surface (display->compositor); + xdg_surface = xdg_wm_base_get_xdg_surface (display->xdg_wm_base, surface); + xdg_surface_add_listener (xdg_surface, &xdg_surface_listener, NULL); + xdg_toplevel = xdg_surface_get_toplevel (xdg_surface); + xdg_toplevel_add_listener (xdg_toplevel, &xdg_toplevel_listener, NULL); + + cursor_surface = wl_compositor_create_surface (display->compositor); + cursor_theme = wl_cursor_theme_load (NULL, 24, display->shm); + cursor = wl_cursor_theme_get_cursor (cursor_theme, "left_ptr"); + cursor2 = wl_cursor_theme_get_cursor (cursor_theme, "right_ptr"); + g_assert_nonnull (cursor); + g_assert_nonnull (cursor2); + + init_surface (); + wl_surface_commit (surface); + + running = TRUE; + while (running) + { + if (wl_display_dispatch (display->display) == -1) + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} + diff -Nru mutter-44.0/src/tests/wayland-test-clients/meson.build mutter-44.1/src/tests/wayland-test-clients/meson.build --- mutter-44.0/src/tests/wayland-test-clients/meson.build 2023-03-19 10:55:05.000000000 +0000 +++ mutter-44.1/src/tests/wayland-test-clients/meson.build 2023-04-25 16:16:17.000000000 +0000 @@ -57,6 +57,12 @@ 'name': 'fullscreen', }, { + 'name': 'kms-cursor-hotplug-helper', + 'extra_deps': [ + wayland_cursor_dep, + ], + }, + { 'name': 'dma-buf-scanout', 'extra_deps': [ libdrm_dep, diff -Nru mutter-44.0/src/tests/x11-test.sh mutter-44.1/src/tests/x11-test.sh --- mutter-44.0/src/tests/x11-test.sh 2023-03-19 10:55:05.000000000 +0000 +++ mutter-44.1/src/tests/x11-test.sh 2023-04-25 16:16:17.000000000 +0000 @@ -1,4 +1,4 @@ -#!/usr/bin/bash +#!/bin/bash set -e diff -Nru mutter-44.0/src/wayland/meta-cursor-sprite-wayland.h mutter-44.1/src/wayland/meta-cursor-sprite-wayland.h --- mutter-44.0/src/wayland/meta-cursor-sprite-wayland.h 2023-03-19 10:55:05.000000000 +0000 +++ mutter-44.1/src/wayland/meta-cursor-sprite-wayland.h 2023-04-25 16:16:17.000000000 +0000 @@ -25,6 +25,7 @@ #include "wayland/meta-wayland-surface.h" #define META_TYPE_CURSOR_SPRITE_WAYLAND meta_cursor_sprite_wayland_get_type () +META_EXPORT_TEST G_DECLARE_FINAL_TYPE (MetaCursorSpriteWayland, meta_cursor_sprite_wayland, META, CURSOR_SPRITE_WAYLAND, MetaCursorSprite) diff -Nru mutter-44.0/src/wayland/meta-wayland-buffer.c mutter-44.1/src/wayland/meta-wayland-buffer.c --- mutter-44.0/src/wayland/meta-wayland-buffer.c 2023-03-19 10:55:05.000000000 +0000 +++ mutter-44.1/src/wayland/meta-wayland-buffer.c 2023-04-25 16:16:17.000000000 +0000 @@ -877,10 +877,9 @@ return NULL; } - g_return_val_if_fail (scanout, NULL); - - g_signal_connect (scanout, "scanout-failed", - G_CALLBACK (on_scanout_failed), buffer); + if (scanout) + g_signal_connect (scanout, "scanout-failed", + G_CALLBACK (on_scanout_failed), buffer); return scanout; } diff -Nru mutter-44.0/src/wayland/meta-wayland.c mutter-44.1/src/wayland/meta-wayland.c --- mutter-44.0/src/wayland/meta-wayland.c 2023-03-19 10:55:05.000000000 +0000 +++ mutter-44.1/src/wayland/meta-wayland.c 2023-04-25 16:16:17.000000000 +0000 @@ -60,6 +60,7 @@ #endif #ifdef HAVE_NATIVE_BACKEND +#include "backends/native/meta-frame-native.h" #include "backends/native/meta-renderer-native.h" #endif @@ -79,6 +80,7 @@ gboolean is_wayland_egl_display_bound; MetaWaylandFilterManager *filter_manager; + GHashTable *frame_callback_sources; } MetaWaylandCompositorPrivate; G_DEFINE_TYPE_WITH_PRIVATE (MetaWaylandCompositor, meta_wayland_compositor, @@ -90,6 +92,15 @@ struct wl_display *display; } WaylandEventSource; +typedef struct +{ + GSource source; + + MetaWaylandCompositor *compositor; + ClutterStageView *stage_view; + int64_t target_presentation_time_us; +} FrameCallbackSource; + static gboolean wayland_event_source_prepare (GSource *base, int *timeout) @@ -143,6 +154,199 @@ return &wayland_source->source; } +static void +emit_frame_callbacks_for_stage_view (MetaWaylandCompositor *compositor, + ClutterStageView *stage_view) +{ + GList *l; + int64_t now_us; + + now_us = g_get_monotonic_time (); + + l = compositor->frame_callback_surfaces; + while (l) + { + 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 (!meta_surface_actor_wayland_is_view_primary (actor, + stage_view)) + continue; + + actor_surface = META_WAYLAND_ACTOR_SURFACE (surface->role); + meta_wayland_actor_surface_emit_frame_callbacks (actor_surface, + now_us / 1000); + + compositor->frame_callback_surfaces = + g_list_delete_link (compositor->frame_callback_surfaces, l_cur); + } +} + +static gboolean +frame_callback_source_dispatch (GSource *source, + GSourceFunc callback, + gpointer user_data) +{ + FrameCallbackSource *frame_callback_source = (FrameCallbackSource *) source; + MetaWaylandCompositor *compositor = frame_callback_source->compositor; + ClutterStageView *stage_view = frame_callback_source->stage_view; + + emit_frame_callbacks_for_stage_view (compositor, stage_view); + g_source_set_ready_time (source, -1); + + return G_SOURCE_CONTINUE; +} + +static void +frame_callback_source_finalize (GSource *source) +{ + FrameCallbackSource *frame_callback_source = (FrameCallbackSource *) source; + + g_signal_handlers_disconnect_by_data (frame_callback_source->stage_view, + source); +} + +static GSourceFuncs frame_callback_source_funcs = { + .dispatch = frame_callback_source_dispatch, + .finalize = frame_callback_source_finalize, +}; + +static void +on_stage_view_destroy (ClutterStageView *stage_view, + GSource *source) +{ + FrameCallbackSource *frame_callback_source = (FrameCallbackSource *) source; + MetaWaylandCompositor *compositor = frame_callback_source->compositor; + MetaWaylandCompositorPrivate *priv = + meta_wayland_compositor_get_instance_private (compositor); + + g_hash_table_remove (priv->frame_callback_sources, stage_view); +} + +static GSource* +frame_callback_source_new (MetaWaylandCompositor *compositor, + ClutterStageView *stage_view) +{ + FrameCallbackSource *frame_callback_source; + g_autofree char *name = NULL; + GSource *source; + + source = g_source_new (&frame_callback_source_funcs, + sizeof (FrameCallbackSource)); + frame_callback_source = (FrameCallbackSource *) source; + + name = + g_strdup_printf ("[mutter] Wayland frame callbacks for stage view (%p)", + stage_view); + g_source_set_name (source, name); + g_source_set_priority (source, CLUTTER_PRIORITY_REDRAW); + g_source_set_can_recurse (source, FALSE); + + frame_callback_source->compositor = compositor; + frame_callback_source->stage_view = stage_view; + + g_signal_connect (stage_view, + "destroy", + G_CALLBACK (on_stage_view_destroy), + source); + + return &frame_callback_source->source; +} + +static GSource* +ensure_source_for_stage_view (MetaWaylandCompositor *compositor, + ClutterStageView *stage_view) +{ + MetaWaylandCompositorPrivate *priv = + meta_wayland_compositor_get_instance_private (compositor); + GSource *source; + + source = g_hash_table_lookup (priv->frame_callback_sources, stage_view); + if (!source) + { + source = frame_callback_source_new (compositor, stage_view); + g_hash_table_insert (priv->frame_callback_sources, stage_view, source); + g_source_attach (source, NULL); + g_source_unref (source); + } + + return source; +} + +static void +on_after_update (ClutterStage *stage, + ClutterStageView *stage_view, + ClutterFrame *frame, + MetaWaylandCompositor *compositor) +{ +#if defined(HAVE_NATIVE_BACKEND) + MetaContext *context = meta_wayland_compositor_get_context (compositor); + MetaBackend *backend = meta_context_get_backend (context); + MetaFrameNative *frame_native; + FrameCallbackSource *frame_callback_source; + GSource *source; + int64_t min_render_time_allowed_us; + + if (!META_IS_BACKEND_NATIVE (backend)) + { + emit_frame_callbacks_for_stage_view (compositor, stage_view); + return; + } + + frame_native = meta_frame_native_from_frame (frame); + + source = ensure_source_for_stage_view (compositor, stage_view); + frame_callback_source = (FrameCallbackSource *) source; + + if (meta_frame_native_had_kms_update (frame_native) || + !clutter_frame_get_min_render_time_allowed (frame, + &min_render_time_allowed_us)) + { + g_source_set_ready_time (source, -1); + emit_frame_callbacks_for_stage_view (compositor, stage_view); + } + else + { + int64_t target_presentation_time_us; + int64_t source_ready_time_us; + + if (!clutter_frame_get_target_presentation_time (frame, + &target_presentation_time_us)) + target_presentation_time_us = 0; + + if (g_source_get_ready_time (source) != -1 && + frame_callback_source->target_presentation_time_us < + target_presentation_time_us) + emit_frame_callbacks_for_stage_view (compositor, stage_view); + + source_ready_time_us = target_presentation_time_us - + min_render_time_allowed_us; + + if (source_ready_time_us <= g_get_monotonic_time ()) + { + g_source_set_ready_time (source, -1); + emit_frame_callbacks_for_stage_view (compositor, stage_view); + } + else + { + frame_callback_source->target_presentation_time_us = + target_presentation_time_us; + g_source_set_ready_time (source, source_ready_time_us); + } + } +#else + emit_frame_callbacks_for_stage_view (compositor, stage_view); +#endif +} + void meta_wayland_compositor_set_input_focus (MetaWaylandCompositor *compositor, MetaWindow *window) @@ -215,44 +419,6 @@ meta_wayland_seat_update (compositor->seat, event); } -static void -on_after_update (ClutterStage *stage, - ClutterStageView *stage_view, - ClutterFrame *frame, - MetaWaylandCompositor *compositor) -{ - GList *l; - int64_t now_us; - - now_us = g_get_monotonic_time (); - - l = compositor->frame_callback_surfaces; - while (l) - { - 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 (!meta_surface_actor_wayland_is_view_primary (actor, - stage_view)) - continue; - - actor_surface = META_WAYLAND_ACTOR_SURFACE (surface->role); - meta_wayland_actor_surface_emit_frame_callbacks (actor_surface, - now_us / 1000); - - compositor->frame_callback_surfaces = - g_list_delete_link (compositor->frame_callback_surfaces, l_cur); - } -} - static MetaWaylandOutput * get_output_for_stage_view (MetaWaylandCompositor *compositor, ClutterStageView *stage_view) @@ -477,6 +643,7 @@ g_clear_pointer (&compositor->seat, meta_wayland_seat_free); g_clear_pointer (&priv->filter_manager, meta_wayland_filter_manager_free); + g_clear_pointer (&priv->frame_callback_sources, g_hash_table_destroy); g_clear_pointer (&compositor->display_name, g_free); g_clear_pointer (&compositor->wayland_display, wl_display_destroy); @@ -500,6 +667,9 @@ g_error ("Failed to create the global wl_display"); priv->filter_manager = meta_wayland_filter_manager_new (compositor); + priv->frame_callback_sources = + g_hash_table_new_full (NULL, NULL, NULL, + (GDestroyNotify) g_source_destroy); } static void diff -Nru mutter-44.0/src/wayland/meta-wayland-cursor-surface.c mutter-44.1/src/wayland/meta-wayland-cursor-surface.c --- mutter-44.0/src/wayland/meta-wayland-cursor-surface.c 2023-03-19 10:55:05.000000000 +0000 +++ mutter-44.1/src/wayland/meta-wayland-cursor-surface.c 2023-04-25 16:16:17.000000000 +0000 @@ -219,6 +219,10 @@ META_WAYLAND_CURSOR_SURFACE (object); MetaWaylandCursorSurfacePrivate *priv = meta_wayland_cursor_surface_get_instance_private (cursor_surface); + MetaWaylandSurface *surface = + meta_wayland_surface_role_get_surface (META_WAYLAND_SURFACE_ROLE (object)); + MetaWaylandSeat *seat = surface->compositor->seat; + MetaWaylandPointer *pointer = seat->pointer; MetaWaylandFrameCallback *cb, *next; wl_list_for_each_safe (cb, next, &priv->frame_callbacks, link) @@ -242,6 +246,8 @@ g_clear_object (&priv->buffer); } + meta_wayland_pointer_update_cursor_surface (pointer); + G_OBJECT_CLASS (meta_wayland_cursor_surface_parent_class)->dispose (object); } diff -Nru mutter-44.0/src/wayland/meta-wayland-data-device.c mutter-44.1/src/wayland/meta-wayland-data-device.c --- mutter-44.0/src/wayland/meta-wayland-data-device.c 2023-03-19 10:55:05.000000000 +0000 +++ mutter-44.1/src/wayland/meta-wayland-data-device.c 2023-04-25 16:16:17.000000000 +0000 @@ -522,7 +522,9 @@ MetaWaylandDragGrab *drag_grab; drag_grab = wl_container_of (grab, drag_grab, keyboard_grab); - meta_wayland_data_source_cancel (drag_grab->drag_data_source); + 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); meta_dnd_actor_drag_finish (META_DND_ACTOR (drag_grab->feedback_actor), diff -Nru mutter-44.0/src/wayland/meta-wayland-data-source.c mutter-44.1/src/wayland/meta-wayland-data-source.c --- mutter-44.0/src/wayland/meta-wayland-data-source.c 2023-03-19 10:55:05.000000000 +0000 +++ mutter-44.1/src/wayland/meta-wayland-data-source.c 2023-04-25 16:16:17.000000000 +0000 @@ -49,6 +49,17 @@ guint drop_performed : 1; } MetaWaylandDataSourcePrivate; +enum +{ + PROP_0, + + PROP_COMPOSITOR, + + N_PROPS +}; + +static GParamSpec *props[N_PROPS] = { 0 }; + G_DEFINE_TYPE_WITH_PRIVATE (MetaWaylandDataSource, meta_wayland_data_source, G_TYPE_OBJECT); @@ -146,6 +157,46 @@ } static void +meta_wayland_data_source_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + MetaWaylandDataSource *source = META_WAYLAND_DATA_SOURCE (object); + MetaWaylandDataSourcePrivate *priv = + meta_wayland_data_source_get_instance_private (source); + + switch (prop_id) + { + case PROP_COMPOSITOR: + priv->compositor = g_value_get_object (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + +static void +meta_wayland_data_source_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + MetaWaylandDataSource *source = META_WAYLAND_DATA_SOURCE (object); + MetaWaylandDataSourcePrivate *priv = + meta_wayland_data_source_get_instance_private (source); + + switch (prop_id) + { + case PROP_COMPOSITOR: + g_value_set_pointer (value, priv->compositor); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + +static void meta_wayland_data_source_init (MetaWaylandDataSource *source) { MetaWaylandDataSourcePrivate *priv = @@ -162,6 +213,8 @@ GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->finalize = meta_wayland_data_source_finalize; + object_class->set_property = meta_wayland_data_source_set_property; + object_class->get_property = meta_wayland_data_source_get_property; klass->send = meta_wayland_data_source_real_send; klass->target = meta_wayland_data_source_real_target; @@ -169,8 +222,18 @@ 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; -} + props[PROP_COMPOSITOR] = + g_param_spec_object ("compositor", + "compositor", + "MetaWaylandCompositor", + META_TYPE_WAYLAND_COMPOSITOR, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS); + + g_object_class_install_properties (object_class, N_PROPS, props); +} static void data_source_offer (struct wl_client *client, @@ -245,12 +308,14 @@ meta_wayland_data_source_new (MetaWaylandCompositor *compositor, 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); + MetaWaylandDataSource *source; + MetaWaylandDataSourcePrivate *priv; + + source = g_object_new (META_TYPE_WAYLAND_DATA_SOURCE, + "compositor", compositor, + NULL); + priv = meta_wayland_data_source_get_instance_private (source); - priv->compositor = compositor; meta_wayland_data_source_set_resource (source, resource); wl_resource_set_implementation (resource, &data_source_interface, source, destroy_data_source); diff -Nru mutter-44.0/src/wayland/meta-wayland-dma-buf.c mutter-44.1/src/wayland/meta-wayland-dma-buf.c --- mutter-44.0/src/wayland/meta-wayland-dma-buf.c 2023-03-19 10:55:05.000000000 +0000 +++ mutter-44.1/src/wayland/meta-wayland-dma-buf.c 2023-04-25 16:16:17.000000000 +0000 @@ -157,7 +157,20 @@ MetaGpuKms *gpu_kms; if (!META_IS_BACKEND_NATIVE (backend)) - return FALSE; + { + MetaEgl *egl = meta_backend_get_egl (backend); + ClutterBackend *clutter_backend = + meta_backend_get_clutter_backend (backend); + CoglContext *cogl_context = + clutter_backend_get_cogl_context (clutter_backend); + EGLDisplay egl_display = cogl_egl_context_get_egl_display (cogl_context); + + return meta_egl_has_extensions (egl, + egl_display, + NULL, + "EGL_EXT_image_dma_buf_import_modifiers", + NULL); + } renderer_native = META_RENDERER_NATIVE (meta_backend_get_renderer (backend)); gpu_kms = meta_renderer_native_get_primary_gpu (renderer_native); diff -Nru mutter-44.0/src/wayland/meta-wayland-xdg-shell.c mutter-44.1/src/wayland/meta-wayland-xdg-shell.c --- mutter-44.0/src/wayland/meta-wayland-xdg-shell.c 2023-03-19 10:55:05.000000000 +0000 +++ mutter-44.1/src/wayland/meta-wayland-xdg-shell.c 2023-04-25 16:16:17.000000000 +0000 @@ -642,6 +642,9 @@ MetaWaylandXdgPositioner *xdg_positioner; MetaWaylandTransaction *transaction; + if (!meta_wayland_surface_get_window (surface)) + return; + xdg_positioner = g_memdup2 (wl_resource_get_user_data (positioner_resource), sizeof (MetaWaylandXdgPositioner)); @@ -1192,7 +1195,7 @@ top_xdg_popup = meta_wayland_xdg_popup_from_surface (top_popup_surface); xdg_popup_send_popup_done (top_xdg_popup->resource); - meta_wayland_popup_destroy (top_xdg_popup->popup); + meta_wayland_popup_dismiss (top_xdg_popup->popup); if (top_xdg_popup == xdg_popup) break; @@ -1236,6 +1239,12 @@ if (xdg_popup->setup.parent_surface) finish_popup_setup (xdg_popup); + if (!meta_wayland_surface_get_window (surface)) + { + meta_wayland_actor_surface_queue_frame_callbacks (actor_surface, pending); + return; + } + if (pending->xdg_positioner) { MetaWindow *window, *parent_window; @@ -1358,6 +1367,9 @@ int geometry_scale; int x, y; + if (!xdg_popup->resource) + return; + /* If the parent surface was destroyed, its window will be destroyed * before the popup receives the parent-destroy signal. This means that * the popup may potentially get temporary focus until itself is destroyed. diff -Nru mutter-44.0/src/wayland/meta-xwayland-dnd.c mutter-44.1/src/wayland/meta-xwayland-dnd.c --- mutter-44.0/src/wayland/meta-xwayland-dnd.c 2023-03-19 10:55:05.000000000 +0000 +++ mutter-44.1/src/wayland/meta-xwayland-dnd.c 2023-04-25 16:16:17.000000000 +0000 @@ -595,11 +595,14 @@ } static MetaWaylandDataSource * -meta_wayland_data_source_xwayland_new (MetaXWaylandDnd *dnd) +meta_wayland_data_source_xwayland_new (MetaXWaylandDnd *dnd, + MetaWaylandCompositor *compositor) { MetaWaylandDataSourceXWayland *source_xwayland; - source_xwayland = g_object_new (META_TYPE_WAYLAND_DATA_SOURCE_XWAYLAND, NULL); + source_xwayland = g_object_new (META_TYPE_WAYLAND_DATA_SOURCE_XWAYLAND, + "compositor", compositor, + NULL); source_xwayland->dnd = dnd; return META_WAYLAND_DATA_SOURCE (source_xwayland); @@ -737,7 +740,7 @@ for (i = 0; i < nitems_ret; i++) { - const gchar *mime_type; + char *mime_type; if (atoms[i] == utf8_string) { @@ -748,6 +751,7 @@ mime_type = XGetAtomName (xdisplay, atoms[i]); meta_wayland_data_source_add_mime_type (source, mime_type); + XFree (mime_type); } XFree (atoms); @@ -933,7 +937,7 @@ if (!(event->data.l[1] & 1)) { /* Mimetypes are contained in this message */ - const gchar *mimetype; + char *mimetype; gint i; struct wl_array *source_mime_types; @@ -950,6 +954,7 @@ mimetype = XGetAtomName (xdisplay, event->data.l[i]); meta_wayland_data_source_add_mime_type (dnd->source, mimetype); + XFree (mimetype); } } } @@ -1030,7 +1035,7 @@ if (event->owner != None && event->owner != x11_display->selection.xwindow && focus && meta_xwayland_is_xwayland_surface (focus)) { - dnd->source = meta_wayland_data_source_xwayland_new (dnd); + dnd->source = meta_wayland_data_source_xwayland_new (dnd, compositor); meta_wayland_data_device_set_dnd_source (&compositor->seat->data_device, dnd->source); diff -Nru mutter-44.0/src/x11/events.c mutter-44.1/src/x11/events.c --- mutter-44.0/src/x11/events.c 2023-03-19 10:55:05.000000000 +0000 +++ mutter-44.1/src/x11/events.c 2023-04-25 16:16:17.000000000 +0000 @@ -1129,7 +1129,7 @@ process_selection_request (MetaX11Display *x11_display, XEvent *event) { - XSelectionEvent reply; + XSelectionEvent reply = { 0 }; if (x11_display->wm_sn_selection_window != event->xselectionrequest.owner || x11_display->wm_sn_atom != event->xselectionrequest.selection) diff -Nru mutter-44.0/src/x11/meta-selection-source-x11.c mutter-44.1/src/x11/meta-selection-source-x11.c --- mutter-44.0/src/x11/meta-selection-source-x11.c 2023-03-19 10:55:05.000000000 +0000 +++ mutter-44.1/src/x11/meta-selection-source-x11.c 2023-04-25 16:16:17.000000000 +0000 @@ -21,6 +21,7 @@ #include "config.h" +#include "meta/meta-x11-errors.h" #include "x11/meta-x11-selection-input-stream-private.h" #include "x11/meta-selection-source-x11-private.h" @@ -47,7 +48,7 @@ GInputStream *stream; GError *error = NULL; - stream = meta_x11_selection_input_stream_new_finish (res, NULL, NULL, &error); + stream = meta_x11_selection_input_stream_new_finish (res, &error); if (stream) g_task_return_pointer (task, stream, g_object_unref); @@ -75,7 +76,6 @@ gpointer user_data) { MetaSelectionSourceX11 *source_x11 = META_SELECTION_SOURCE_X11 (source); - Display *xdisplay = meta_x11_display_get_xdisplay (source_x11->x11_display); GTask *task; task = g_task_new (source, cancellable, callback, user_data); @@ -91,7 +91,7 @@ mimetype = "UTF8_STRING"; meta_x11_selection_input_stream_new_async (source_x11->x11_display, - XGetAtomName (xdisplay, source_x11->xselection), + source_x11->xselection, mimetype, source_x11->timestamp, G_PRIORITY_DEFAULT, @@ -155,15 +155,23 @@ for (i = 0; i < n_atoms; i++) { - const gchar *mimetype; + char *mimetype; + meta_x11_error_trap_push (display); mimetype = XGetAtomName (xdisplay, atoms[i]); + meta_x11_error_trap_pop (display); + + if (!mimetype) + continue; + mimetypes = g_list_prepend (mimetypes, g_strdup (mimetype)); utf8_text_plain_found |= strcmp (mimetype, "text/plain;charset=utf-8") == 0; text_plain_found |= strcmp (mimetype, "text/plain") == 0; utf8_string_found |= strcmp (mimetype, "UTF8_STRING") == 0; string_found |= strcmp (mimetype, "STRING") == 0; + + XFree (mimetype); } /* Ensure non-x11 clients get well-known mimetypes */ @@ -211,7 +219,7 @@ GInputStream *stream; GError *error = NULL; - stream = meta_x11_selection_input_stream_new_finish (res, NULL, NULL, &error); + stream = meta_x11_selection_input_stream_new_finish (res, &error); if (error) { g_task_return_error (task, error); @@ -236,7 +244,6 @@ GAsyncReadyCallback callback, gpointer user_data) { - Display *xdisplay = meta_x11_display_get_xdisplay (x11_display); MetaSelectionSourceX11 *source; GTask *task; @@ -251,7 +258,7 @@ g_task_set_task_data (task, source, g_object_unref); meta_x11_selection_input_stream_new_async (x11_display, - XGetAtomName (xdisplay, xselection), + xselection, "TARGETS", timestamp, G_PRIORITY_DEFAULT, diff -Nru mutter-44.0/src/x11/meta-sync-counter.c mutter-44.1/src/x11/meta-sync-counter.c --- mutter-44.0/src/x11/meta-sync-counter.c 2023-03-19 10:55:05.000000000 +0000 +++ mutter-44.1/src/x11/meta-sync-counter.c 2023-04-25 16:16:17.000000000 +0000 @@ -222,7 +222,7 @@ { MetaWindow *window = sync_counter->window; MetaX11Display *x11_display = window->display->x11_display; - XClientMessageEvent ev; + XClientMessageEvent ev = { 0, }; gint64 wait_serial; if (sync_counter->sync_request_counter == None || diff -Nru mutter-44.0/src/x11/meta-x11-selection.c mutter-44.1/src/x11/meta-x11-selection.c --- mutter-44.0/src/x11/meta-x11-selection.c 2023-03-19 10:55:05.000000000 +0000 +++ mutter-44.1/src/x11/meta-x11-selection.c 2023-04-25 16:16:17.000000000 +0000 @@ -185,7 +185,7 @@ { Display *xdisplay = meta_x11_display_get_xdisplay (x11_display); GList* mimetypes = NULL; - const gchar *atom_name; + char *atom_name; char *retval; mimetypes = meta_selection_get_mimetypes (selection, selection_type); @@ -213,6 +213,7 @@ } g_list_free_full (mimetypes, g_free); + XFree (atom_name); return retval; } @@ -248,11 +249,14 @@ return FALSE; } - output = meta_x11_selection_output_stream_new (x11_display, event->requestor, - XGetAtomName (xdisplay, event->selection), - XGetAtomName (xdisplay, event->target), - XGetAtomName (xdisplay, event->property), - "ATOM", 32, event->time); + output = meta_x11_selection_output_stream_new (x11_display, + event->requestor, + event->selection, + event->target, + event->property, + XInternAtom (xdisplay, "ATOM", False), + 32, + event->time); bytes = mimetypes_to_bytes (mimetypes, x11_display->xdisplay); g_list_free_full (mimetypes, g_free); @@ -284,10 +288,10 @@ { output = meta_x11_selection_output_stream_new (x11_display, event->requestor, - XGetAtomName (xdisplay, event->selection), - XGetAtomName (xdisplay, event->target), - XGetAtomName (xdisplay, event->property), - XGetAtomName (xdisplay, event->target), + event->selection, + event->target, + event->property, + event->target, 8, event->time); meta_selection_transfer_async (selection, diff -Nru mutter-44.0/src/x11/meta-x11-selection-input-stream.c mutter-44.1/src/x11/meta-x11-selection-input-stream.c --- mutter-44.0/src/x11/meta-x11-selection-input-stream.c 2023-03-19 10:55:05.000000000 +0000 +++ mutter-44.1/src/x11/meta-x11-selection-input-stream.c 2023-04-25 16:16:17.000000000 +0000 @@ -41,9 +41,7 @@ Atom xselection; Atom xtarget; Atom xproperty; - const char *type; Atom xtype; - int format; GTask *pending_task; uint8_t *pending_data; @@ -342,8 +340,7 @@ get_selection_property (MetaX11Display *x11_display, Window owner, Atom property, - Atom *ret_type, - gint *ret_format) + Atom *ret_type) { gulong nitems; gulong nbytes; @@ -386,7 +383,6 @@ } *ret_type = prop_type; - *ret_format = prop_format; return g_bytes_new_with_free_func (data, length, @@ -399,7 +395,6 @@ XFree (data); *ret_type = None; - *ret_format = 0; return NULL; } @@ -414,7 +409,6 @@ Window xwindow; GBytes *bytes; Atom type; - gint format; char *target; xdisplay = priv->x11_display->xdisplay; @@ -434,7 +428,7 @@ bytes = get_selection_property (priv->x11_display, xwindow, xevent->xproperty.atom, - &type, &format); + &type); if (bytes == NULL) { @@ -486,8 +480,7 @@ { bytes = get_selection_property (priv->x11_display, xwindow, xevent->xselection.property, - &priv->xtype, &priv->format); - priv->type = XGetAtomName (xdisplay, priv->xtype); + &priv->xtype); g_task_return_pointer (task, g_object_ref (stream), g_object_unref); @@ -524,7 +517,7 @@ void meta_x11_selection_input_stream_new_async (MetaX11Display *x11_display, - const char *selection, + Atom xselection, const char *target, guint32 timestamp, int io_priority, @@ -548,7 +541,7 @@ x11_display->selection.input_streams = g_list_prepend (x11_display->selection.input_streams, stream); - priv->xselection = XInternAtom (x11_display->xdisplay, selection, False); + priv->xselection = xselection; priv->xtarget = XInternAtom (x11_display->xdisplay, target, False); priv->xproperty = XInternAtom (x11_display->xdisplay, "META_SELECTION", False); priv->window = XCreateWindow (x11_display->xdisplay, @@ -575,12 +568,9 @@ GInputStream * meta_x11_selection_input_stream_new_finish (GAsyncResult *result, - const char **type, - int *format, GError **error) { MetaX11SelectionInputStream *stream; - MetaX11SelectionInputStreamPrivate *priv; GTask *task; g_return_val_if_fail (g_task_is_valid (result, NULL), NULL); @@ -592,12 +582,5 @@ if (!stream) return NULL; - priv = meta_x11_selection_input_stream_get_instance_private (stream); - - if (type) - *type = priv->type; - if (format) - *format = priv->format; - return G_INPUT_STREAM (stream); } diff -Nru mutter-44.0/src/x11/meta-x11-selection-input-stream-private.h mutter-44.1/src/x11/meta-x11-selection-input-stream-private.h --- mutter-44.0/src/x11/meta-x11-selection-input-stream-private.h 2023-03-19 10:55:05.000000000 +0000 +++ mutter-44.1/src/x11/meta-x11-selection-input-stream-private.h 2023-04-25 16:16:17.000000000 +0000 @@ -33,7 +33,7 @@ GInputStream) void meta_x11_selection_input_stream_new_async (MetaX11Display *x11_display, - const char *selection, + Atom xselection, const char *target, guint32 timestamp, int io_priority, @@ -41,8 +41,6 @@ GAsyncReadyCallback callback, gpointer user_data); GInputStream * meta_x11_selection_input_stream_new_finish (GAsyncResult *result, - const char **type, - int *format, GError **error); gboolean meta_x11_selection_input_stream_xevent (MetaX11SelectionInputStream *stream, diff -Nru mutter-44.0/src/x11/meta-x11-selection-output-stream.c mutter-44.1/src/x11/meta-x11-selection-output-stream.c --- mutter-44.0/src/x11/meta-x11-selection-output-stream.c 2023-03-19 10:55:05.000000000 +0000 +++ mutter-44.1/src/x11/meta-x11-selection-output-stream.c 2023-04-25 16:16:17.000000000 +0000 @@ -657,10 +657,10 @@ GOutputStream * meta_x11_selection_output_stream_new (MetaX11Display *x11_display, Window requestor, - const char *selection, - const char *target, - const char *property, - const char *type, + Atom selection, + Atom target, + Atom property, + Atom type, int format, gulong timestamp) { @@ -675,10 +675,10 @@ priv->x11_display = x11_display; priv->xwindow = requestor; - priv->xselection = XInternAtom (x11_display->xdisplay, selection, False); - priv->xtarget = XInternAtom (x11_display->xdisplay, target, False); - priv->xproperty = XInternAtom (x11_display->xdisplay, property, False); - priv->xtype = XInternAtom (x11_display->xdisplay, type, False); + priv->xselection = selection; + priv->xtarget = target; + priv->xproperty = property; + priv->xtype = type; priv->format = format; priv->timestamp = timestamp; diff -Nru mutter-44.0/src/x11/meta-x11-selection-output-stream-private.h mutter-44.1/src/x11/meta-x11-selection-output-stream-private.h --- mutter-44.0/src/x11/meta-x11-selection-output-stream-private.h 2023-03-19 10:55:05.000000000 +0000 +++ mutter-44.1/src/x11/meta-x11-selection-output-stream-private.h 2023-04-25 16:16:17.000000000 +0000 @@ -34,10 +34,10 @@ GOutputStream * meta_x11_selection_output_stream_new (MetaX11Display *x11_display, Window window, - const char *selection, - const char *target, - const char *property, - const char *type, + Atom selection, + Atom target, + Atom property, + Atom type, int format, gulong timestamp); diff -Nru mutter-44.0/src/x11/window-x11.c mutter-44.1/src/x11/window-x11.c --- mutter-44.0/src/x11/window-x11.c 2023-03-19 10:55:05.000000000 +0000 +++ mutter-44.1/src/x11/window-x11.c 2023-04-25 16:16:17.000000000 +0000 @@ -126,7 +126,7 @@ * data[1] time stamp */ - XClientMessageEvent ev; + XClientMessageEvent ev = { 0 }; MetaX11Display *x11_display = window->display->x11_display; ev.type = ClientMessage; @@ -235,7 +235,7 @@ MetaX11Display *x11_display = window->display->x11_display; MetaWindowX11 *window_x11 = META_WINDOW_X11 (window); MetaWindowX11Private *priv = meta_window_x11_get_instance_private (window_x11); - XEvent event; + XEvent event = { 0 }; g_assert (!window->override_redirect); @@ -706,7 +706,7 @@ XShapeSelectInput (x11_display->xdisplay, window->xwindow, NoEventMask); meta_window_ungrab_keys (window); - meta_display_ungrab_window_buttons (window->display, window->xwindow); + meta_display_ungrab_window_buttons (window->display, window); meta_display_ungrab_focus_window_button (window->display, window); meta_x11_error_trap_pop (x11_display); @@ -3861,7 +3861,7 @@ meta_window_grab_keys (window); if (window->type != META_WINDOW_DOCK && !window->override_redirect) { - meta_display_grab_window_buttons (window->display, window->xwindow); + meta_display_grab_window_buttons (window->display, window); meta_display_grab_focus_window_button (window->display, window); }